20150530 pgunconf-pgbench-semi-structured-benchmark

39
PostgreSQL Unconference (2015-05-30) XML, hsotre, JSON, JSONB pgbench Benchmark ぬこ@横浜 (@nuko_yokohama)

Upload: toshi-harada

Post on 26-Jul-2015

980 views

Category:

Technology


2 download

TRANSCRIPT

PostgreSQL Unconference(2015-05-30)

XML, hsotre, JSON, JSONB pgbench Benchmark

ぬこ@横浜 (@nuko_yokohama)

自己紹介ぬこ@横浜です

詳細はググれ ( ください )

またおまえか・・・と言わず聞いてください

ネタは JSONB

また JSONB か・・・と言わず聞いてください

今日は、ちょこっとだけPostgreSQL 9.5 の

話もしますよ。

本題

PostgreSQL非構造データ型

XML 型hstore 型JSON 型JSONB 型

XML 型

XML を格納するデータ型属性、階層、順序、名前空間対応

本体機能 (configure で指定 )格納時に XML パースを行なう型自体に比較演算機能はないxpath によるアクセスが可能libxml2 ライブラリに依存

hstore

Key-Value store データ型Contrib モジュールネストはできない。

部分更新インタフェースありPostgreSQL 8.3 ~対応

JSON/JSONB の詳細は過去の発表スライドを

見ろ(ください)※ 説明するとなげーし

( PGCon 2014 とか JPUG 勉強会とか)

JSON

その名のとおり JSON を格納する型部分更新インタフェースなし

PostgreSQL 9.2 ~対応

JSONB

JSON をバイナリで格納する型検索性能の向上

GIN インデックス対応部分更新インタフェースあり (9.5 ? )

PostgreSQL 9.4 ~対応

各データ型の処理イメージ

XML 型の処理XML 文字列

XML パーサ

XML 型(文字列)

XML 文字列

関数の結果

(そのまま出力)

格納時

取り出し時

xpath関数

XML パーサ関数処理

xpath 処理

パーサではチェックのみを行う

PostgreSQLストレージ

hstore 型の処理 ( たぶん )hstore 文字列

hstore パーサ

hstore 型(バイナリ)

hstore 文字列

関数の結果

文字列化

格納時

取り出し時

hstore関数

関数処理 バイナリを直接解釈して関数実行

パーサは動作しない

PostgreSQLストレージシリアライズ

JSON 型の処理JSON 文字列

JSON ツリーJSON パーサ

JSON 型(文字列)

JSON 文字列

関数の結果

(そのまま出力)

格納時

取り出し時

JSON関数

JSON パーサ関数処理

JSON ツリー

パーサで生成したJSONツリーは捨てられる

PostgreSQLストレージ

JSONB 型の処理JSON 文字列

JSON ツリーJSON パーサ

JSONB 型(バイナリ)

JSON 文字列

関数の結果

文字列化

格納時

取り出し時

JSONB関数

関数処理 バイナリを直接解釈して関数実行

パーサは動作しない

PostgreSQLストレージシリアライズ

XML, hstore, JSON 比較データ型 表現能力 格納領域 処理性能XML ◎ △ △hstore △ ○ ◎JSON ○ ○ ○JSONB ○ ○ ◎

XML は表現能力は高いが扱いにくいhstore はシンプルだが速いJSONB は良いとこ取り?⇒ 用途で使い分け可能

本当か?

じゃあ、pgbench で勝負だっ!

各データ型を使ってpgbench_accountspgbench_branches

pgbench_tellerspgbench_history

を 1 カラムで表現する

pgbench モデルのテーブル

bench=# \d pgbench_accounts; Table "public.pgbench_accounts" Column | Type | Modifiers ----------+---------------+----------- aid | integer | not null bid | integer | abalance | integer | filler | character(84) | Indexes: "pgbench_accounts_pkey" PRIMARY KEY, btree (aid)

通常の pgbench モデル

XML モデルbench_xml=# \d accounts Table "public.accounts" Column | Type | Modifiers --------+------+----------- data | xml | Indexes: "xml_aid_idx" btree (((xpath('/accounts/aid/text()'::text, data)::text[])[1]::integer))

pgbench モデルのテーブルbench_hstore=# \d accounts Table "public.accounts" Column | Type | Modifiers --------+--------+----------- data | hstore | Indexes: "hstore_aid_idx" btree (((data -> 'aid'::text)::integer))

hstore モデル

JSONB モデル

bench_json=# \d accounts Table "public.accounts" Column | Type | Modifiers --------+------+----------- data | json | Indexes: "json_aid_idx" btree (((data ->> 'aid'::text)::integer))

JSON モデル

( JSON モデルとだいたいおなじ)今回は GIN インデックスパターンは

使いません

pgbench モデルのクエリ

BEGIN;UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;SELECT abalance FROM pgbench_accounts WHERE aid = :aid;UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);END;

通常の pgbench モデル(抜粋)

pgbench モデルのクエリ

UPDATE accounts SET data = xmlelement(name accounts, null, xmlelement(name aid, null, ((xpath('/accounts/aid/text()', data))::text[])[1]), xmlelement(name bid, null, ((xpath('/accounts/bid/text()', data))::text[])[1]), xmlelement(name abalance, null, (((xpath('/accounts/abalance/text()', data))::text[])[1])::int + :delta ), xmlelement(name filler, null, ((xpath('/accounts/filler/text()', data))::text[])[1])) WHERE (xpath('/accounts/aid/text()', data)::text[])[1]::int = :aid;

SELECT ((xpath('/accounts/abalance/text()', data))::text[])[1]::int FROM accounts WHERE ((xpath('/accounts/aid/text()', data))::text[])[1]::int = :aid;

INSERT INTO history (data) VALUES ( xmlelement(name history, null, xmlelement(name tid, null, :tid), xmlelement(name bid, null, :bid), xmlelement(name aid, null, :aid), xmlelement(name delta, null, :delta), xmlelement(name mtime, null, CURRENT_TIMESTAMP), xmlelement(name filler, null, ' ')));

XML の pgbench モデル(抜粋)

pgbench モデルのクエリ

UPDATE accounts SET data = data || hstore('abalance', ((data->'abalance')::int + :delta)::text ) WHERE (data->'aid')::int = :aid;

SELECT data->'abalance' FROM accounts WHERE (data->'aid')::int = :aid;

INSERT INTO history (data) VALUES ( hstore( ARRAY['tid','bid','aid','delta','mtime', 'filler'], ARRAY[ ( :tid )::text, ( :bid )::text, ( :aid )::text, ( :delta )::text, CURRENT_TIMESTAMP::text, ' ']));

hstore の pgbench モデル(抜粋)

pgbench モデルのクエリUPDATE accounts SET data = json_build_object( 'aid', (data->>'aid')::int, 'bid', (data->>'bid')::int, 'abalance', (data->>'abalance')::int + :delta , 'filler', data->>'filler') WHERE (data->>'aid')::int = :aid;

SELECT data->>'abalance' FROM accounts WHERE (data->>'aid')::int = :aid;

INSERT INTO history (data) VALUES ( json_build_object( 'tid', :tid, 'bid', :bid, 'aid', :aid, 'delta', :delta, 'mtime', CURRENT_TIMESTAMP, 'filler', ' '));

JSON の pgbench モデル(抜粋)

pgbench モデルのクエリUPDATE accounts SET data = json_build_object( 'aid', (data->>'aid')::int, 'bid', (data->>'bid')::int, 'abalance', (data->>'abalance')::int + :delta , 'filler', data->>'filler')::jsonb WHERE (data->>'aid')::int = :aid;

SELECT data->>'abalance' FROM accounts WHERE (data->>'aid')::int = :aid;

INSERT INTO history (data) VALUES ( json_build_object('tid', :tid, 'bid', :bid, 'aid', :aid, 'delta', :delta, 'mtime', CURRENT_TIMESTAMP, 'filler', ' ')::jsonb);

JSONB の pgbench モデル(抜粋)

pgbench モデルのクエリ

UPDATE accounts SET data = data || jsonb_build_object('abalance', (data->>'abalance')::int + :delta) WHERE (data->>'aid')::int = :aid;

SELECT data->>'abalance' FROM accounts WHERE (data->>'aid')::int = :aid;

INSERT INTO history (data) VALUES ( jsonb_build_object( 'tid', :tid, ' bid', :bid, 'aid', :aid, 'delta', :delta, 'mtime', CURRENT_TIMESTAMP, 'filler', ' '));

JSONB(9.5) の pgbench モデル(抜粋)

PostgreSQL 9.5 では hstore 型と似たような部分更新の演算子 ( || ) が追加された!(あと jsonb_build_object が追加されたっぽい)

測定環境とモデルLet's note SX4

VMWare + CentOS 7.0PostgreSQL 9.5-devel

Scale Factor = 10( accounts:100 万件)

ホントはAWS EC2のいい感じのインスタンスを使いたかっけど間に合わなかった

ロード時間とインデックス作成時間

XML おせえ(インデックス作成も)JSON チョットハヤイ

XML

hstore

JSON

JSONB

0.000 5000.000 10000.000 15000.000 20000.000 25000.000 30000.000

ロード時間およびインデックス作成時間

インデックス作成時間 (ms)

ロード時間 (ms)

このモデルだとカラム数が少ないからJSONB はやや冗長になるのかな

XML

hstore

JSON

JSONB

0 50000000 100000000 150000000 200000000 250000000

テーブルサイズ /インデックスサイズ

インデックスサイズ

テーブルサイズ

accounts100 万件更新時間WHERE 句なし UPDATE 文で実施

XML テラおせえhstore ギガ速い

JSONB-9.5 部分更新の効果も見える

XML

hstore

JSON

JSONB

JSONB-9.5

0 10000 20000 30000 40000 50000 60000 70000 80000

76042

5292

12508

12241

8829

100万件更新時間 (ms)

pgbench 走行同時接続数 =2

走行時間 =300 秒

XML おせえ・ hstore 速いJSONB 9.5 部分更新の効果は低い?

XML

hstore

JSON

JSONB

JSONB-9.5

通常レコード

0 200 400 600 800 1000 1200 1400 1600 1800 2000

467.436

1360.219

1066.437

1149.694

1103.781

1708.898

pgbenchスループット (tps)

XML おせえ・ hstore 速いSELECT はあんまり差がないね

UPDATE accounts

SELECT accounts

UPDATE tellers

UPDATE branches

INSERT history

END

0 0.2 0.4 0.6 0.8 1 1.2 1.4 1.6 1.8 2

pgbenchレイテンシ (ms)

XML

hstore

JSON

JSONB

JSONB-9.5通常レコード

XML, hstore, JSON 比較データ型 表現能力 格納領域 処理性能XML ◎ △ △hstore △ ○ ◎JSON ○ ○ ○JSONB ○ ○ ◎

だいたいあってた!よかった!

ちょい微妙?

おしまい