PostgreSQL 9.4 GINインデックスの評価、JSONBデータ型の使い方:PostgreSQLガイダンス(1)(2/2 ページ)
PostgreSQL 9.4で注目が集まるGINインデックスの性能を検証、バイナリJSONデータ型の使い方も紹介する。
バイナリ版JSONデータ型(JSONB)の登場
PostgreSQLではバージョン9.2からJSONデータ型が使用可能でした。JSONとは、JavaScriptに始まり、いまやさまざまな言語、環境、ツールで場所で使用されているデータ表現形式です。
PostgreSQLのJSON型は、基本的にはtext型やvarchar型と同じ文字列データ型で、値を格納するときにJSONとしての構文チェックが行われるようになっています。また、いくつかのJSON処理関数や演算子が用意されています。
PostgreSQL 9.4では、いままでのJSON型に加えてJSONBという新たなデータ型が追加されました。JSONBのBはバイナリ(binary)のBを表しています。その名前の通り、バイナリデータとしてデータを格納します。
JSONB型はおおむねJSON型と同じように使用できます。JSON型で使える演算子や関数のほとんどはJSONB型でも使えます。また、相互に型変換できます。その上でJSONB型にはJSON型に対していくつかの違いと優位点があります。
(1)GINインデックスと「含まれる?」を問う演算子
JSONB型にはGINインデックスを作成できます。また、GINインデックスが利用可能な、要素が含まれるかを問ういくつかの演算子が追加されています。次に例を示します。
db1=# SELECT '{"A":1, "B":2, "C":[3,4,5]}'::jsonb @> '{"B":2}'jsonb ; ⇒ 左辺JSONデータの中に右辺JSONデータに含まれるので true が返ります db1=# SELECT '{"A":1, "B":2, "C":[3,4,5]}'::jsonb ? 'A' ; ⇒ 右辺の文字列が JSON の ハッシュキーとして含まれるので true が返ります db1=# SELECT '["A", "B", "C"]'::jsonb ? 'A' ; ⇒ 右辺の文字列が JSON の配列要素として含まれるので true が返ります
この他、PostgreSQL 9.4本体の配布物には含まれませんが、JSONB型に対応した、階層化されたJSONデータの中身を検索する演算子を提供する拡張モジュール「jsquery」(詳細は後述)が開発されています。ここでもGINインデックスが利用されています。
(2)JSONB型におけるデータのデータ正規化
JSON型はJSON文法を守る範囲で任意の文字列を格納できますが、JSONB型ではデータは正規化されます。
JSON型では下記二つのデータは異なるものとして扱われますが、JSONB型では同一のものとして扱われます。要素の間の空白文字はいくつあっても同じとされ、また、同一キーの重複定義は後の定義値だけが採用されます。
'{ "A":123, "B":456, "C":789 }' '{ "A":0, "A":123, "B" : 456, "C" : 789 }'
jsqueryの世界
PostgreSQL 9.4対応のjsquery拡張モジュールについてもう少し詳しく見ていきましょう。
jsquery拡張モジュールの導入
jsquery拡張モジュールは以下のように、GitHubの配布URL(https://github.com/akorotkov/jsquery/archive/master.zip)からダウンロードします。PostgreSQL 9.4のPATHが通っている環境で、取得したzipファイルを展開、jsquery-masterディレクトリからUSE_PGXS=1を指定してmakeを実行、インストールします。
その上で、使用するデータベースにおいて(この例ではdb1)、CREATE EXTENSION命令を実行します。
ちなみに、この手順はPostgreSQLの拡張モジュール全般に共通する手順ですので、覚えておくとよいでしょう。
$ wget -O jsquery-master.zip \ https://github.com/akorotkov/jsquery/archive/master.zip $ unzip jsquery-master.zip $ cd jsquery-master $ make UES_PGXS=1 $ su -c 'make UES_PGXS=1 install' $ psql db1 db1=# CREATE EXTENSION jsquery ; CREATE EXTENSION
jsquery拡張モジュールを使ってみる
jsquery拡張モジュールの準備ができたら、早速試しに使ってみましょう。
ここでは、以下のような、構造が一定しない多段に入れ子になったJSONデータのカラムを持つ「t_info」テーブルを用意します。
db1=# SELECT * FROM t_info; id | j ----+-------------------------------------------------------------- 1 | {"f1": {"f1": {"f1": [585, 19, 526], "f2": {"f1": 185, "f2": … 2 | [518, 375, [{"f1": {"f1": 329, "f2": 936, "f3": 702}, "f2": … 3 | {"f1": [836, 363, [{"f1": 396, "f2": 95, "f3": 197}, [377, 1 … : | :
また、jsquery拡張モジュールで用意されている演算子クラスを指定して、GINインデックスを作成しておきます。これはデータ階層全体をインデックスに含めるようにするものです。2種類の演算子クラスはインデックス作成方式が若干異なり、インデックスが適用できる演算子の種類に違いがあります。
db1=# CREATE INDEX idxj1 ON t_info USING gin (j jsonb_value_path_ops); db1=# CREATE INDEX idxj2 ON t_info USING gin (j jsonb_path_value_ops);
これにより以下のような問い合わせがGINインデックス検索を通して実行可能になります。
db1=# SELECT * FROM t_info WHERE j @@ 'f1.# IN (1,2,3)' ⇒ トップ直下の f1 キー値が配列であって、1、2、3 いずれかの値を含む db1=# SELECT * FROM t_info WHERE j @@ '%.f2.f3 = *' ⇒ トップ直下の任意キー値から "f2" → "f3" という階層を持つ db1=# SELECT * FROM t_info WHERE j @@ '*.f1 < 100' ⇒ いずれかの階層にある f1 キーの値が 100 以下である
この検索問い合わせの表現能力は、各種のJSON検索言語でできることをおおむねカバーしています。PostgreSQLはバージョン9.4のリリースを期に、JSONに特化した専用のデータベースに匹敵する能力を持つようになっています。
jsqueryは今のところ、PostgreSQL本体とは切り離された外部配布の拡張モジュールであり、ドキュメントも充実しているとはいえませんが、PostgreSQL上でドキュメント指向データベースのように動作することから、今後の展開に大きな可能性が感じられます。
次回は
今回は、PostgreSQL 9.4で実装される機能のうち、GINインデックス高速化とJSON/JSONB型の実装を中心に紹介しました。次回は、運用管理に関連した部分に注目して見ていきます。お楽しみに。
関連情報:PostgreSQLガイド
オープンソースのRDBMSである「PostgreSQL」に関する情報を集約しています。インストールから設定、運用、パフォーマンスチューニングの基礎解説などの他、最新機能レビューも紹介しています。
Copyright © ITmedia, Inc. All Rights Reserved.