連載
» 2014年09月04日 19時21分 公開

PostgreSQLガイダンス(1):PostgreSQL 9.4 GINインデックスの評価、JSONBデータ型の使い方 (2/2)

[高塚遥,SRA OSS, Inc.]
前のページへ 1|2       

バイナリ版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ガイド

postgresqlguide

オープンソースのRDBMSである「PostgreSQL」に関する情報を集約しています。インストールから設定、運用、パフォーマンスチューニングの基礎解説などの他、最新機能レビューも紹介しています。


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。