PostgreSQLのjsonbデータ型について
5593 ワード
PostgreSQL 9.4はjsonbという新しい機能をロードしています.GINインデックスを支援するJSON資料を格納できる新しい資料です.言い換えれば、この機能は、間もなく更新される中で最も重要なのは、それさえ重要でない場合は、Postgresを本データベースシステムの推奨位置にファイルしましょう.
9.2から、統合JSONの資料タイプはすでに存在し、一連の機能(例えば資料生成と資料解体機能)を持ち、9.3の新しい操作者もいる.JSON資料タイプを使用すると、資料は全く同じコピーとして保存され、機能はそれ以上に動作し、バックグラウンド動作の再分析も必要となる.
この心得JSOnb資料タイプは分解された2元形式で格納されているので、この資料を挿入するとJSONよりも効率的で、バックグラウンドで再分析する必要がなくなり、より迅速に実行でき、GINインデックスも兼ね備えています.最後に、私たちは実際に読者にjsonbを使ってjsonの代わりにプログラムを作ることをお勧めします(もちろん、必要に応じてjsonを使うこともできます).jsonbは同じオペレータと機能を使用していることを覚えておいてください.読者たちは私の前の投稿を見て、何か啓発を得ることができます(あるいはPostgresのファイルを見てください).
JSOnbがどのように働いているのかを見ながら、JSONと比較してみましょう.採用したテストデータは860万のgeobaseタイプのデータで、都市名、国家コード(ここでは完全なリストを参照)など多くのフィールドを含む約1.1 Gサイズです.まず、下位レプリケーション(raw copy)によってこれらのデータをデータベースの新しいテーブルに格納し、その後、このテーブルを充填因子が100のテーブルのセットを通じてJSON/JSOnbに変換し、それぞれどれだけの空間を占めているかを見てみましょう.
JSOnbデータを生成するのに少し時間がかかりますが、大きさの違いはありますか?
JSONデータ上でインデックスを作成するには9.3バージョンから開始します.たとえばオペレータを使用します(テキストを返すため'->>'が使用されます.クエリーによってインデックスは異なるキーワードを使用します).
この例では、計画(planner)はbitmapインデックススキャンとともに、以前に生成されたインデックスを使用することができる.
今、JSONBの新しい特徴はオペレータ@>を含むデータ容量をチェックすることです.このデータはGINでインデックスできます.このオペレータデータも含まれていますか?,|と?&(指定されたキーワードが存在するかどうかを確認するため).GINインデックスは、2種類のオペレータに役立ちます.
デフォルトのオペレータクラス、前の4つ;
jsonb_hash_opsは、@>のみをサポートしていますが、データを検索するとパフォーマンスがよく、ディスク領域が小さくなります.
次のように動作します.
アプリケーションのニーズに応じて、BTreeがJSONデータ上に構築されたインデックスのタイプなど、スペース消費の低いインデックスを採用したいかもしれません.GINインデックスは、すべてのJSONフィールドを上書きし、容量をチェックするため、より多くの利点があります.
9.2から、統合JSONの資料タイプはすでに存在し、一連の機能(例えば資料生成と資料解体機能)を持ち、9.3の新しい操作者もいる.JSON資料タイプを使用すると、資料は全く同じコピーとして保存され、機能はそれ以上に動作し、バックグラウンド動作の再分析も必要となる.
この心得JSOnb資料タイプは分解された2元形式で格納されているので、この資料を挿入するとJSONよりも効率的で、バックグラウンドで再分析する必要がなくなり、より迅速に実行でき、GINインデックスも兼ね備えています.最後に、私たちは実際に読者にjsonbを使ってjsonの代わりにプログラムを作ることをお勧めします(もちろん、必要に応じてjsonを使うこともできます).jsonbは同じオペレータと機能を使用していることを覚えておいてください.読者たちは私の前の投稿を見て、何か啓発を得ることができます(あるいはPostgresのファイルを見てください).
JSOnbがどのように働いているのかを見ながら、JSONと比較してみましょう.採用したテストデータは860万のgeobaseタイプのデータで、都市名、国家コード(ここでは完全なリストを参照)など多くのフィールドを含む約1.1 Gサイズです.まず、下位レプリケーション(raw copy)によってこれらのデータをデータベースの新しいテーブルに格納し、その後、このテーブルを充填因子が100のテーブルのセットを通じてJSON/JSOnbに変換し、それぞれどれだけの空間を占めているかを見てみましょう.
=# COPY geodata FROM '$HOME/Downloads/allCountries.txt';
COPY 8647839
=# CREATE TABLE geodata_jsonb (data jsonb) with (fillfactor=100);
CREATE TABLE
=# CREATE TABLE geodata_json (data json) with (fillfactor=100);
CREATE TABLE
=# \timing
Timing is on.
=# INSERT INTO geodata_json SELECT row_to_json(geodata) FROM geodata;
INSERT 0 8647839
Time: 287158.457 ms
=# INSERT INTO geodata_jsonb SELECT row_to_json(geodata)::jsonb FROM geodata;
INSERT 0 8647839
Time: 425825.967 ms
JSOnbデータを生成するのに少し時間がかかりますが、大きさの違いはありますか?
=# SELECT pg_size_pretty(pg_relation_size('geodata_json'::regclass)) AS json,
pg_size_pretty(pg_relation_size('geodata_jsonb'::regclass)) AS jsonb;
json | jsonb
---------+---------
3274 MB | 3816 MB
(1 row)
JSONデータ上でインデックスを作成するには9.3バージョンから開始します.たとえばオペレータを使用します(テキストを返すため'->>'が使用されます.クエリーによってインデックスは異なるキーワードを使用します).
=# CREATE INDEX geodata_index ON
geodata_json ((data->>'country_code'), (data->>'asciiname'));
CREATE INDEX
=# SELECT pg_size_pretty(pg_relation_size('geodata_index'::regclass))
AS json_index;
json_index
------------
310 MB
(1 row)
=# SELECT (data->>'population')::int as population,
data->'latitude' as latitude,
data->'longitude' as longitude
FROM geodata_json WHERE data->>'country_code' = 'JP' AND
data->>'asciiname' = 'Tokyo' AND
(data->>'population')::int != 0;
population | latitude | longitude
------------+----------+-----------
8336599 | 35.6895 | 139.69171
(1 row)
=# -- Explain of previous query
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on geodata_json (cost=6.78..865.24 rows=215 width=32)
Recheck Cond: (((data ->> 'country_code'::text) = 'JP'::text) AND ((data ->> 'asciiname'::text) = 'Tokyo'::text))
Filter: (((data ->> 'population'::text))::integer <> 0)
-> Bitmap Index Scan on geodata_index (cost=0.00..6.72 rows=216 width=0)
Index Cond: (((data ->> 'country_code'::text) = 'JP'::text) AND ((data ->> 'asciiname'::text) = 'Tokyo'::text))
Planning time: 0.172 ms
(6 rows)
この例では、計画(planner)はbitmapインデックススキャンとともに、以前に生成されたインデックスを使用することができる.
今、JSONBの新しい特徴はオペレータ@>を含むデータ容量をチェックすることです.このデータはGINでインデックスできます.このオペレータデータも含まれていますか?,|と?&(指定されたキーワードが存在するかどうかを確認するため).GINインデックスは、2種類のオペレータに役立ちます.
デフォルトのオペレータクラス、前の4つ;
jsonb_hash_opsは、@>のみをサポートしていますが、データを検索するとパフォーマンスがよく、ディスク領域が小さくなります.
次のように動作します.
=# CREATE INDEX geodata_gin ON geodata_jsonb
USING GIN (data jsonb_hash_ops);
CREATE INDEX
=# SELECT (data->>'population')::int as population,
data->'latitude' as latitude,
data->'longitude' as longitude
FROM geodata_jsonb WHERE data @> '{"country_code": "JP", "asciiname": "Tokyo"}' AND
(data->>'population')::int != 0;
population | latitude | longitude
------------+----------+-----------
8336599 | 35.6895 | 139.69171
(1 row)
=# SELECT pg_size_pretty(pg_relation_size('geodata_gin'::regclass)) AS jsonb_gin;
jsonb_gin
-----------
1519 MB
(1 row)
=# -- EXPLAIN of previous query
QUERY PLAN
-------------------------------------------------------------------------------------
Bitmap Heap Scan on geodata_jsonb (cost=131.01..31317.76 rows=8605 width=418)
Recheck Cond: (data @> '{"asciiname": "Tokyo", "country_code": "JP"}'::jsonb)
Filter: (((data ->> 'population'::text))::integer <> 0)
-> Bitmap Index Scan on geodata_gin (cost=0.00..128.86 rows=8648 width=0)
Index Cond: (data @> '{"asciiname": "Tokyo", "country_code": "JP"}'::jsonb)
Planning time: 0.134 ms
アプリケーションのニーズに応じて、BTreeがJSONデータ上に構築されたインデックスのタイプなど、スペース消費の低いインデックスを採用したいかもしれません.GINインデックスは、すべてのJSONフィールドを上書きし、容量をチェックするため、より多くの利点があります.