본문 바로가기

소프트웨어-이야기/데이터 저장소 + 시각화

(PostgreSQL) JSON VS JSONB

RDB에 JSON 포맷을 저장할 때, 평소처럼 텍스트 포맷으로 저장할지, JSON Format을 적용할지 고민하게 된다. 

뫼비우스의 띠 같은 삶을 사는 나는 딱 1년전에도 비슷한 고민을 했었다.

( 작년에 조사한 글 :  👉 [MariaDB]RDB 속에서 NOSQL 사용하기 👈)

작년에는 리서치만 해보고 말았는데, 올해에는 PostgreSQL에 JSON 타입을 실제로 적용해봐야겠다. 🐜🐜🐜

고럼 이만 포스팅 시작~ ㅎ.ㅎ 

PostgreSQL의 JSON 타입은 크게 2가지이다. JSON, JSONB 두가지 유형이다. JSON Type은 9.4 버전부터 추가되었다. 


공통점

둘다 JSON 포맷 유효성체크를 한다.


차이점

데이터 저장 방식

JSON은 들어온 그대로 값을 저장한다. 그런데 JSONB는 그대로 저장하지 않는다. 문자열 사이의 공백도 제거해주고, KEY 순서도 보장하지 않는다. 

SELECT '{"bar": "baz",     "balance": 7.77, "active":false}'::json;
                      json                       
-------------------------------------------------
 {"bar": "baz",     "balance": 7.77, "active":false}
(1 row) SELECT '{"bar": "baz", "balance": 7.77, "active":false}'::jsonb;
jsonb -------------------------------------------------- {"bar": "baz", "active": false, "balance": 7.77} (1 row)


디스크사용량

JSONB가 JSON보다 좀더 많은 디스크를 사용한다. ( But. 항상 그런건 아니다 )


인덱싱

JSON은 인덱싱이 불가능하다. 그런데 JSONB는 인덱싱이 가능하다. 

요런 문서가 있다고 하면, 

{
    "guid": "9c36adc1-7fb5-4d5b-83b4-90356a46061a",
    "name": "Angela Barton",
    "is_active": true,
    "company": "Magnafone",
    "address": "178 Howard Place, Gulf, Washington, 702",
    "registered": "2009-11-07T08:53:22 +08:00",
    "latitude": 19.793713,
    "longitude": 86.513373,
    "tags": [
        "enim",
        "aliquip",
        "qui"
    ]
}

요런식으로 쿼리를 날릴 때, 인덱싱을 태울 수 있다. ( Json타입에도 쿼리를 날릴 수 있는지는 테스트해봐야겠다 )

SELECT jdoc->'guid', jdoc->'name' FROM api WHERE jdoc @> '{"company": "Magnafone"}';

함수

이런 함수는 JSONB에서만 사용할 수 있다.

-- String exists as array element:
SELECT '["foo", "bar", "baz"]'::jsonb ? 'bar';

-- String exists as object key:
SELECT '{"foo": "bar"}'::jsonb ? 'foo';

위의 함수를 JSON 타입에 적용하려고 하면 아래와 같은 에러가 발생한다.

 😠😠



주의사항

JSON 필드에 많은 양의 데이터를 저장할 수는 있다. 

그런데 JSON 필드에 있는 값을 변경할 때, JSON이 속한 ROW에 락이 걸리기 때문에, 적정 수준의 데이터를 저장해야한다. 


쿼리

jsonb에 대한 aggregate 쿼리는 느린편이다. 


요약

JSON 타입은 입력받은 텍스트값을 DB에 그대로 저장한다. 그래서 쓰기 비용이 크지 않다. 그러나 읽기 비용이 있다. 

반면 JSONB 타입은 입력받은 데이터를 바이너리 포맷으로 저장한다. 그래서 쓰기 비용이 크다. 

그러나 인덱싱이 가능하고, 데이터 파싱 비용이 들지 않기 때문에 읽기 비용이 적다는 이점이 있다.

특별한 사유가 없다면 JSONB를 사용하는게 좋다고 한다. 🤔 


Django와 Postgresql에 관련된 여담

Django JSONField는 Postgresql만 지원한다. 

그리고 DJANGO JSONField는 JSONB만 지원한다. 만약 JSON을 쓰러면, jsonfield 라이브러리를 활용해야할 듯. 



참고 자료

(PostgreSQL) DataType JSON

Faster Operations with the JSONB Data Type in PostgreSQL