Objaśnienie JSONB wprowadzone przez PostgreSQL

346

PostgreSQL właśnie wprowadził JSONB i jest już popularny w wiadomościach hakerów . Byłoby wspaniale, gdyby ktoś mógł wyjaśnić, czym różni się od Hstore i JSON wcześniej obecnych w PostgreSQL. Jakie są zalety i ograniczenia i kiedy ktoś powinien rozważyć jego użycie?

Peeyush
źródło
4
Z PGCon2014: youtube.com/…
msanford
5
@CraigRinger url nie jest wystarczająco precyzyjny, teraz, rok później, nie wskazuje nawet wystarczająco blisko treści związanych z JSONB.
berkus
2
@berkus Myślałem, że mam link do konkretnego postu. Jak frustrujące.
Craig Ringer
1
Wskazuje konkretny film.
talonx

Odpowiedzi:

458

Po pierwsze, hstorejest modułem contrib, który pozwala tylko przechowywać pary klucz => wartości, gdzie klucze i wartości mogą być tylko texts (jednak wartości mogą być również sql NULLs).

Oba json& jsonbpozwala przechowywać prawidłową wartość JSON (zdefiniowaną w specyfikacji ).

F.ex. Są to ważne reprezentacje JSON: null, true, [1,false,"string",{"foo":"bar"}], {"foo":"bar","baz":[null]}- hstoreto tylko mały podzbiór w porównaniu do tego, co jest w stanie JSON (ale jeśli trzeba tylko ten podzbiór, jest w porządku).

Jedyną różnicą między json& jsonbjest ich przechowywanie:

  • json jest przechowywany w formacie zwykłego tekstu, natomiast
  • jsonb jest przechowywany w jakiejś reprezentacji binarnej

Istnieją 3 główne konsekwencje tego:

  • jsonbzwykle zajmuje więcej miejsca na dysku niż json(czasem nie)
  • jsonb kompilacja danych wejściowych zajmuje więcej czasu niż json
  • jsonoperacje zajmują znacznie więcej czasu niż jsonb(i parsowanie również musi być wykonywane za każdym razem, gdy wykonujesz jakąś operację o jsonwpisanej wartości)

Gdy jsonbbędzie dostępny w wersji stabilnej, pojawią się dwa główne przypadki użycia, w których można łatwo wybierać między nimi:

  1. Jeśli pracujesz tylko z reprezentacją JSON w swojej aplikacji, PostgreSQL służy tylko do przechowywania i pobierania tej reprezentacji, powinieneś użyć json.
  2. Jeśli wykonujesz wiele operacji na wartości JSON w PostgreSQL lub korzystasz z indeksowania w niektórych polach JSON, powinieneś użyć jsonb.
pozs
źródło
1
cześć, skoro ma reprezentację binarną, dlaczego jsonbtego nie obsługuje? UPDATE test SET data->'a' = 123 WHERE id = 1;odCREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu
1
Kokizzu, jest to możliwe w wersji 9.5. wiki.postgresql.org/wiki/…
ChelowekKot
1
Wystarczy dodać, jednym z powodów może być również korzystają jsonna jsonbto, czy ze względu na starszych kod zużywających swój jsonzależy od zamawiającego z jsonpola i nie można ich kolejność.
djdrzzy
4
Ponieważ, ze względu na wcześniejsze wersje: w JSON nie ma semantycznej różnicy, jeśli pary klucz-wartość obiektu (tabela, mapa, skrót, jakkolwiek to jest wywołane w języku hosta) są uporządkowane inaczej. Jeśli na tym polegasz, faktycznie używasz czegoś innego niż JSON. - W textprzeciwieństwie do json: ten ostatni jest wyposażony w sprawdzanie poprawności JSON, więc po niepoprawnym JSON nie powiedzie się tylko przy wstawianiu, zamiast za każdym razem, gdy aplikacja go czyta (ponieważ otrzymuje niepoprawną reprezentację). Możesz również bezpiecznie przesyłać te ostatnie do jsonbbazy danych.
pozs
2
To świetny post na temat wyjaśniania szczegółów implementacji dla JSONB ( pgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html )
manugupt1
132

Peeyush:

Krótka odpowiedź brzmi:

  • Jeśli wykonujesz wiele operacji JSON wewnątrz PostgreSQL, takich jak sortowanie, krojenie, splicowanie itp., Powinieneś używać JSONB ze względu na szybkość.
  • Jeśli potrzebujesz indeksowanych wyszukiwań dla arbitralnych wyszukiwań kluczy w JSON, powinieneś użyć JSONB.
  • Jeśli nie wykonujesz żadnej z powyższych czynności, prawdopodobnie powinieneś użyć JSON.
  • Jeśli chcesz zachować porządkowanie kluczy, białe znaki i duplikaty kluczy, powinieneś użyć JSON.

Aby uzyskać dłuższą odpowiedź, musisz poczekać, aż zrobię pełny opis „HowTo” bliżej wersji 9.4.

FuzzyChef
źródło
74

Proste wyjaśnienie różnicy między json a jsonb ( oryginalny obraz autorstwa PostgresProfessional ):

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;

          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  • json: przechowywanie tekstu «jak jest»
  • jsonb: brak białych znaków
  • jsonb: brak duplikatów kluczy, ostatnia wygrana klucza
  • jsonb: klucze są posortowane

Więcej w mowie wideo i prezentacji slajdów przez programistów jsonb. Wprowadzili także JsQuery , pg.extension zapewnia potężny język zapytań jsonb

ChelowekKot
źródło
1
Dzięki, zamieniłem go na tekst
ChelowekKot,
56
  • hstore jest bardziej typem „szerokiej kolumny”, jest to płaski (nie zagnieżdżony) słownik par klucz-wartość, zawsze przechowywany w rozsądnie wydajnym formacie binarnym (tablica skrótów, stąd nazwa).
  • jsonprzechowuje dokumenty JSON jako tekst, wykonując walidację, gdy dokumenty są przechowywane, i analizując je w razie potrzeby (np. uzyskując dostęp do poszczególnych pól); powinien obsługiwać całą specyfikację JSON. Ponieważ cały tekst JSON jest przechowywany, jego formatowanie zostaje zachowane.
  • jsonbprzyjmuje skróty ze względu na wydajność: dane JSON są analizowane na wejściu i przechowywane w formacie binarnym, kolejność kluczy w słownikach nie jest utrzymywana, a klucze nie są duplikatami. Dostęp do poszczególnych elementów w polu JSONB jest szybki, ponieważ nie wymaga ciągłego analizowania tekstu JSON. Na wyjściu dane JSON są odtwarzane i formatowanie początkowe jest tracone.

IMO nie ma istotnego powodu, aby nie używać, jsonbgdy jest dostępny, jeśli pracujesz z danymi do odczytu maszynowego.

Ivan Voras
źródło
24

JSONB to „lepsza” wersja JSON.

Spójrzmy na przykład:

SELECT '{"c":0,   "a":2,"a":1}'::json, '{"c":0,   "a":2,"a":1}'::jsonb;
          json          |        jsonb 
------------------------+--------------------- 
 {"c":0,   "a":2,"a":1} | {"a": 1, "c": 0} 
(1 row)
  1. JSON przechowuje białe znaki, dlatego widzimy spacje, gdy klucz „a” jest przechowywany, podczas gdy JSONB nie.
  2. JSON przechowuje wszystkie wartości klucza. To jest powód, dla którego możesz zobaczyć wiele wartości (2 i 1) dla klucza „a”, podczas gdy JSONB „przechowuje” tylko ostatnią wartość.
  3. JSON utrzymuje porządek wstawiania elementów, a JSONB utrzymuje porządek „posortowany”.
  4. Obiekty JSONB są przechowywane jako zdekompresowane pliki binarne w przeciwieństwie do „surowych danych” w JSON, gdzie podczas pobierania nie jest wymagana ponowna analiza danych.
  5. JSONB obsługuje również indeksowanie, co może być znaczącą zaletą.

Ogólnie rzecz biorąc, należy preferować JSONB, chyba że istnieją specjalne potrzeby, takie jak wcześniejsze założenia dotyczące porządkowania kluczy obiektowych.

subodhkarwa
źródło
13

Byłem dziś na pgopen, testy porównawcze są znacznie szybsze niż mongodb, uważam, że było około 500% szybsze dla wybranych. Prawie wszystko było szybsze przynajmniej o 200% w porównaniu z mongodbem, niż jednym wyjątkiem jest teraz aktualizacja, która wymaga całkowitego przepisania całej kolumny json, co mongodb radzi sobie lepiej.

Indeksowanie dżinu w jsonb brzmi niesamowicie.

Również postgres zachowa wewnętrznie typy jsonb i zasadniczo dopasuje to do typów takich jak numeryczne, tekstowe, logiczne itp.

Połączenia będą również możliwe przy użyciu jsonb

Dodaj PLv8 do procedur przechowywanych, a będzie to w zasadzie spełnienie marzeń programistów node.js.

Ponieważ jest przechowywany jako binarny plik jsonb, również usunie wszystkie białe znaki, zmieni kolejność właściwości i usunie duplikaty właściwości przy ostatnim wystąpieniu właściwości.

Poza indeksem podczas zapytania do kolumny jsonb w przeciwieństwie do kolumny json postgres nie musi faktycznie uruchamiać funkcji konwersji tekstu na json w każdym wierszu, co prawdopodobnie zaoszczędzi wiele czasu.

Jan
źródło
8

Jeśli chodzi o różnice między jsoni jsonbtypów danych, to warto wspomnieć o oficjalne wyjaśnienie:

PostgreSQL oferuje dwa typy przechowywania danych JSON: jsoni jsonb. Aby wdrożyć wydajne mechanizmy zapytań dla tych typów danych, PostgreSQL udostępnia również typ danych jsonpath opisany w Rozdziale 8.14.6 .

Te jsoni jsonbtypy danych zaakceptować niemal identycznych zestawów wartości jako wejście. Główną praktyczną różnicą jest wydajność. Typ jsondanych przechowuje dokładną kopię tekstu wejściowego, którą funkcje przetwarzania muszą ponownie przeanalizować przy każdym wykonaniu; podczas gdy jsonbdane są przechowywane w zdekomponowanym formacie binarnym, co sprawia, że ​​wprowadzanie danych jest nieco wolniejsze z powodu dodatkowego obciążenia konwersji, ale znacznie szybsze w przetwarzaniu, ponieważ nie jest wymagane ponowne przetwarzanie. jsonbobsługuje także indeksowanie, co może być znaczącą zaletą.

Ponieważ jsontyp przechowuje dokładną kopię tekstu wejściowego, zachowa semantycznie nieznaczną spację między tokenami, a także porządek kluczy w obiektach JSON. Ponadto, jeśli obiekt JSON w obrębie wartości zawiera ten sam klucz więcej niż jeden raz, wszystkie pary klucz / wartość zostaną zachowane. (Funkcje przetwarzania traktują ostatnią wartość jako operacyjną.) Natomiast jsonbnie zachowuje białych znaków, nie zachowuje kolejności kluczy obiektów i nie zachowuje duplikatów kluczy obiektów. Jeśli na wejściu podano duplikaty kluczy, zachowana zostanie tylko ostatnia wartość.

Ogólnie rzecz biorąc, większość aplikacji powinna preferować przechowywanie danych JSON jako jsonb, chyba że istnieją dość wyspecjalizowane potrzeby, takie jak wcześniejsze założenia dotyczące porządkowania kluczy obiektowych.

PostgreSQL pozwala na kodowanie tylko jednego zestawu znaków na bazę danych. Dlatego typy JSON nie mogą być sztywno zgodne ze specyfikacją JSON, chyba że kodowanie bazy danych to UTF8. Próby bezpośredniego włączenia znaków, których nie można przedstawić w kodowaniu bazy danych, zakończą się niepowodzeniem; i odwrotnie, znaki, które mogą być reprezentowane w kodowaniu bazy danych, ale nie w UTF8, będą dozwolone.

Źródło: https://www.postgresql.org/docs/current/datatype-json.html

Dinei
źródło
7

Inną ważną różnicą, o której nie wspomniano w żadnej odpowiedzi powyżej, jest to, że nie ma operatora równości dla jsontypu, ale jest jeden dla jsonb.

Oznacza to, że nie można używać DISTINCTsłów kluczowych przy wyborze tego jsontypu a i / lub inne pola z tabeli (można użyć DISTINCT ONzamiast tego, ale nie zawsze jest to możliwe ze względu przypadkach takich jak ten ).

Vlasiak
źródło
6

O ile mogę powiedzieć,

  • hstore w obecnym kształcie (w Postgresql 9.3) nie pozwala na zagnieżdżanie innych obiektów i tablic jako wartości jego par klucz / wartość. jednak przyszła łatka hstore pozwoli na zagnieżdżanie. ta łatka nie będzie dostępna w wersji 9.4 i może nie zostać dołączona w najbliższym czasie.

  • json gdyż istnieje obecnie nie pozwala na zagnieżdżanie, ale jest oparty na tekście, a nie pozwala na indeksowanie, co to jest „wolna”

  • jsonb, który zostanie wydany z wersją 9.4, będzie miał bieżące możliwości zagnieżdżania json, a także indeksowanie GIN / GIST w hstore, więc będzie szybki

Osoby pracujące nad postgresql 9.4 wydają się mówić, że nowy, szybki typ jsonb spodoba się osobom, które wybrałyby użycie magazynu danych noSQL, takiego jak MongoDB, ale mogą teraz połączyć relacyjną bazę danych z nieustrukturyzowanymi danymi z możliwością zapytania pod jednym dachem

http://www.databasesoup.com/2014/02/why-hstore2jsonb-is-most-important.html

Benchmarki postgresql 9.4 jsonb wydają się być na równi lub w niektórych przypadkach szybsze niż MongoDB

http://texture.io/alphabetum/postgresql-incl-hstore-vs-mongodb

Erik Szwecja
źródło