PostgreSQLによって導入されたJSONBの説明


345

PostgreSQLはJSONBを導入したばかりで、ハッカーニュースですでにトレンドになっています。誰かが以前にPostgreSQLに存在していたHstoreやJSONとどのように異なるのかを誰かが説明できたら素晴らしいと思います。その利点と制限は何ですか?いつ誰かがそれを使用することを検討すべきですか?


4
PGCon2014から:youtube.com/...
msanford

5
@CraigRingerのURLは十分に正確ではありませんが、1年後、JSONBに関連するコンテンツに十分に近くなっていません。
berkus

2
@berkus特定の投稿にリンクしていると思いました。いらいらする。
クレイグリンガー

1
特定のビデオを指しています。
talonx

回答:


455

まず、hstorecontribモジュールです。これは、キー=>値のペアのみを格納できるようにします。キーと値はtexts のみです(ただし、値はsql NULLsでもかまいません)。

json&の両方でjsonb、有効なJSON specで定義されている)を保存できます。

F.ex. これらは有効なJSON表現である:nulltrue[1,false,"string",{"foo":"bar"}]{"foo":"bar","baz":[null]}- hstoreJSONが可能であるものと比較ほんの少しのサブセットである(ただし、このサブセットのみが必要な場合は、それの罰金)。

json&の唯一の違いjsonbは、ストレージです。

  • json プレーンテキスト形式で保存されますが、
  • jsonb バイナリ表現で保存されます

これには3つの大きな影響があります。

  • jsonb通常、json(場合によっては)よりも多くのディスク領域を格納する
  • jsonb 入力表現から構築するよりも時間がかかります json
  • json操作は、よりもかなり時間がかかりますjsonb(また、json型付きの値で操作を行うたびに解析も実行する必要があります)

ときにjsonb安定したリリースで利用できるようになり、あなたは簡単にそれらの間で選択することができたときに、二つの主要なユースケースがあるでしょう。

  1. アプリケーションでJSON表現のみを使用する場合、PostgreSQLはこの表現の保存と取得にのみ使用されるため、を使用する必要がありますjson
  2. PostgreSQLのJSON値に対して多くの操作を行う場合、または一部のJSONフィールドでインデックスを使用する場合は、を使用する必要がありますjsonb

1
こんにちは、バイナリ表現があるので、なぜjsonbこれをサポートしないのですか?UPDATE test SET data->'a' = 123 WHERE id = 1;からCREATE TABLE test(id SERIAL PRIMARY KEY, data JSONB);
Kokizzu 2014年

1
コキッズ、9.5で可能です。wiki.postgresql.org/wiki/...
ChelowekKot

1
ただ追加する、あなたはまた、使用する可能性のある理由の1 json以上は、jsonbレガシー上の理由から、あなたのコードは、あなたが消費している場合でjsonの順序に依存しているjsonフィールドと、彼らは並べ替えることができません。
djdrzzy

4
従来の理由から、JSONでは、オブジェクト(テーブル、マップ、ハッシュ、ホスト言語で呼び出されるものは何でも)のキーと値のペアの順序が異なる場合、意味上の違いはありません。これに依存している場合は、実際にはJSONとは異なるものを使用しています。-のためにtextjson:後者はJSONの検証が付属していますので、無効なJSONすると、それだけで(それが無効な表現を取得するため)代わりに毎回のアプリケーションがそれを読み込み、挿入時に失敗します。また、後者をjsonbデータベース内に安全にキャストできます。
pozs 2017年

2
これはJSONBのための実装の詳細を説明する上で大きな柱(あるpgeoghegan.blogspot.com/2014/03/what-i-think-of-jsonb.html
manugupt1

131

Peeyush:

短い答えは:

  • PostgreSQL 内でソート、スライス、スプライシングなどの多くのJSON操作を行う場合は、速度上の理由からJSONBを使用する必要があります。
  • JSONの任意のキー検索にインデックス付きルックアップが必要な場合は、JSONBを使用する必要があります。
  • 上記のどちらも実行していない場合は、おそらくJSONを使用する必要があります。
  • キーの順序、空白、重複キーを保持する必要がある場合は、JSONを使用する必要があります。

より長い回答については、私が9.4リリースに近い完全な「ハウツー」記事を書くのを待つ必要があります。


74

jsonとjsonbの違いの簡単な説明(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:「そのまま」のテキストストレージ
  • jsonb:空白なし
  • jsonb:重複するキーはありません、最後のキーが勝ちました
  • jsonb:キーがソートされます

jsonb開発者によるスピーチビデオスライドショーのプレゼンテーションの詳細。また、彼らはJsQueryを導入しました、pg.extensionは強力なjsonbクエリ言語を提供します


1
おかげで、私はそれをテキストに置き換えました
ChelowekKot

55
  • hstore これは「ワイドカラム」のストレージタイプで、キーと値のペアのフラットな(ネストされていない)辞書であり、常に適度に効率的なバイナリ形式(ハッシュテーブル、つまり名前)で保存されます。
  • jsonJSONドキュメントをテキストとして保存し、ドキュメントの保存時に検証を実行し、必要に応じて出力で解析します(つまり、個々のフィールドにアクセスします)。JSON仕様全体をサポートする必要があります。JSONテキスト全体が格納されるため、そのフォーマットは保持されます。
  • jsonbパフォーマンス上の理由でショートカットを使用します。JSONデータは入力で解析され、バイナリ形式で保存されます。辞書のキーの順序は維持されず、どちらも重複キーではありません。JSONBフィールドの個々の要素へのアクセスは、JSONテキストを常に解析する必要がないため、高速です。出力では、JSONデータが再構築され、初期のフォーマットが失われます。

IMO、機械可読データで作業している場合は、使用可能になって使用しない大きな理由はありませんjsonb


24

JSONBはJSONの「より良い」バージョンです。

例を見てみましょう:

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は空白を保存します。これが、キー「a」が保存されているときにスペースを表示できる理由ですが、JSONBはそうではありません。
  2. JSONはキーのすべての値を格納します。これが、キー "a"に対して複数の値(2と1)を表示できる理由ですが、JSONBは最後の値のみを "保存"します。
  3. JSONは要素が挿入される順序を維持し、JSONBは「ソートされた」順序を維持します。
  4. JSONBオブジェクトは、JSONの「生データ」ではなく、解凍されたバイナリとして格納されます。この場合、取得時にデータの再解析は必要ありません。
  5. JSONBはインデックス作成もサポートしており、これは大きな利点となります。

一般に、オブジェクトキーの順序付けに関するレガシー前提などの特別なニーズがない限り、JSONBを優先する必要があります。


13

私は今日pgopenにいましたが、ベンチマークはmongodbよりもはるかに高速です。selectの場合は約500%高速だったと思います。mongodbと比較すると、ほとんどすべてが少なくとも200%高速でしたが、現在の1つの例外は、mongodbがより適切に処理するjson列全体を完全に書き換える必要がある更新です。

jsonbでのジンのインデックス作成はすばらしいですね。

また、postgresはjsonbのタイプを内部で永続化し、基本的にこれを数値、テキスト、ブールなどのタイプと一致させます。

jsonbを使用して結合することもできます

ストアドプロシージャにPLv8を追加します。これは基本的に、node.js開発者にとって夢の実現です。

バイナリjsonbとして保存されているため、すべての空白が削除され、プロパティの順序が変更され、最後に出現したプロパティを使用して重複するプロパティが削除されます。

jsonカラムに対してクエリを実行するときのインデックスは、jsonカラムとは対照的に、postgresは実際に機能を実行してすべての行でテキストをjsonに変換する必要がないため、単独でかなりの時間を節約できます。


7

jsonjsonbデータ型の違いについては、公式の説明に言及する価値があります。

PostgreSQLはJSONデータを格納するための2つのタイプが用意されていますjsonjsonb。これらのデータ型に対して効率的なクエリメカニズムを実装するために、PostgreSQLはセクション8.14.6で説明されているjsonpathデータ型も提供しています。

データ型は、入力として値のほぼ同一のセットを受け入れます。主な実用上の違いは効率の1つです。 データ型は、処理機能を実行するたびに再解析する必要があり、入力されたテキストの正確なコピーを格納します。ながら全く再解析が必要とされないので、データは、大幅に高速化プロセスに起因する追加の変換のオーバーヘッドに入力することがわずかに遅くなり分解バイナリ形式で格納されるが。はインデックス作成もサポートします。これは大きな利点になります。jsonjsonbjsonjsonbjsonb

このjson型は入力テキストの正確なコピーを格納するため、トークン間の意味的に重要ではない空白と、JSONオブジェクト内のキーの順序が保持されます。また、値内のJSONオブジェクトに同じキーが複数含まれている場合、すべてのキーと値のペアが保持されます。(処理関数は最後の値を有効な値と見なします。)対照的に、jsonb空白は保持されず、オブジェクトキーの順序は保持されず、重複するオブジェクトキーは保持されません。入力で重複するキーが指定されている場合、最後の値のみが保持されます。

一般に、jsonbオブジェクトキーの順序に関するレガシーな前提など、特別なニーズがない限り、ほとんどのアプリケーションはJSONデータをとして保存することを優先する 必要があります。

PostgreSQLでは、データベースごとに1つの文字セットエンコーディングしか使用できません。したがって、データベースのエンコードがUTF8でない限り、JSONタイプをJSON仕様に厳密に準拠させることはできません。データベースのエンコーディングで表現できない文字を直接含めようとすると失敗します。逆に、データベースエンコーディングでは表現できるがUTF8では表現できない文字は許可されます。

出典:https : //www.postgresql.org/docs/current/datatype-json.html


6

私の知る限り、

  • 現在(Postgresql 9.3で)存在するhstoreでは、キーと値のペアの値として他のオブジェクトや配列をネストすることはできません。ただし、将来のhstoreパッチではネストが可能になる予定です。このパッチは9.4リリースには含まれず、まもなく含まれる可能性があります。

  • jsonは現在存在しているため、ネスト可能ですが、テキストベースであり、インデックス作成ができないため、「遅い」

  • 9.4でリリースされるjsonbには、jsonの現在のネスト機能と、hstoreのGIN / GISTインデックスが含まれるため、高速になります。

Postgresql 9.4に取り組んでいる人々は、新しい高速jsonbタイプはMongoDBのようなnoSQLデータストアを使用することを選択したが、リレーショナルデータベースをクエリ可能な非構造化データと1つの屋根の下で組み合わせることができるようになると言っているようです。

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

postgresql 9.4 jsonbのベンチマークは、MongoDBと同等か、場合によってはMongoDBよりも高速に見える

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


6

上記の回答で言及されていないもう1つの重要な違いは、json型には等価演算子がないが、には等価演算子があることですjsonb

これは、DISTINCTこのjsonタイプや他のフィールドをテーブルから選択するときにキーワードを使用できないことを意味します(DISTINCT ON代わりに使用できますが、このような場合のために常に使用できるとは限りません)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.