PostgreSQL로 알아보는 JSON과 JSONB 차이점
PostgreSQL은 9.4 버전부터 JSON 타입과 JSONB 타입을 제공한다.
RDB를 사용하면 새로운 서비스를 설계할 때 JSON 형식의 데이터를 적재해야 하는지 고민해야하는 상황이 자주 온다.
JSON.stringify()된 데이터를 Text형태로 저장해서 JSON.parse()를 한 뒤 파싱하여 사용하는 방법도 있지만
PostgreSQL에서는 JSON을 사용하기 위한 강력한 연산자를 제공하고 있다.
PostgrSQL에서 제공하는 JSON과 JSONB 타입의 연산자
연산자 | 오른쪽 자료형 | 설명 | 예제 | 예제 결과 |
-> | int | JSON 배열에서 해당 요소를 JSON 형으로 뽑기(첫번째는 0) | '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 | {"c":"baz"} |
-> | text | 해당 key에 대한 value를 JSON 형으로 뽑기 | '{"a": {"b":"foo"}}'::json->'a' | {"b":"foo"} |
->> | int | -> 연산자와 같으나 리턴값이 text 형 | '[1,2,3]'::json->>2 | 3 |
->> | text | 해당 key에 대한 value를 text 형으로 뽑기 | '{"a":1,"b":2}'::json->>'b' | 2 |
#> | text[] | 패스로 value를 JSON 형으로 뽑기 | '{"a": {"b":{"c": "foo"}}}'::json#>'{a,b}' | {"c": "foo"} |
#>> | text[] | 패스로 value를 text 형으로 뽑기 | '{"a":[1,2,3],"b":[4,5,6]}'::json#>>'{a,2}' | 3 |
위 연산자를 이용해 메모리 상에서 파싱하지 않고 원하는 데이터를 조회 할 수 있다.
JSON과 JSONB 타입의 가장 큰 차이점은 인덱싱이다.
현재 repiar가 true이며, carwash가 false인 데이터를 조회한다고 생각해보자.
{id: 1, option: { "repair": true, "carwash": false }}, {id: 2, option: { "repair": true, "carwash": true }}
컬럼을 JSON 타입으로 선언한 경우 인덱싱을 제공하지 않기 때문에 여러가지 편법을 사용해야한다.
SELECT * FROM market WHERE option LIKE '%{ "repair": true, "carwash": true }%'
위와 같은 형태로 진행하거나, 모든 데이터를 조회한 후 메모리에서 찾는 방법 등을 고민해봐야한다.
JSONB 타입으로 선언한 경우는 인덱싱을 제공하고 있다.
SELECT * FROM market WHERE option->'repair' @> true AND option->'carwash' @> false
와 같이 쿼리가 가능하고, key값의 순서가 변경되어도 상관이 없다.
인덱싱이 가능하다는 장점은 RDB의 성격과도 유사한 점이 있어서 대부분의 경우는 JSONB를 사용하는게 좋다고 한다.
JSON의 경우 쓰기 자원이 덜 들고, 상대적으로 JSONB의 경우 읽기 자원이 덜 든다고 한다. (Postgres 포스팅 발췌) 이 부분에 대한 실제 테스트는 이후에 다뤄보도록 하겠다.
타입 | 쓰기 자원사용 | 읽기 자원사용 |
JSON | 낮음↓ | 높음↑ |
JSONB | 높음↑ | 낮음↓ |
배움의 길은 끝이 없다.