リモートサーバの設定
test=# d sangokushi
テーブル"public.sangokushi"
列 | 型 | 修飾語
------+---------+---------------------------------------------------------
id | integer | not null default nextval('sangokushi_id_seq'::regclass)
data | text |
インデックス :
"meros_gin" gin (data gin_bigm_ops)
sangokushi テーブルの data 列に対して
pg_bigm による N-gram インデックス
を設定している。
17.
ローカルサーバの設定
test=# des sv2_test
外部サーバー一覧
名前| 所有者 | 外部データラッパー
----------+--------+--------------------
sv2_test | nuko | postgres_fdw
(1 行 )
test=# d sangokushi
外部テーブル "public.sangokushi"
列 | 型 | 修飾語 | FDW オプション
------+---------+--------+---------------
id | integer | |
data | text | |
Server: sv2_test
外部サーバ (sv2_test) 上に
外部表 sangokushi を定義する
18.
検索してみる
test=# SELECT dataFROM sangokushi WHERE data LIKE '% 兀突骨 %' LIMIT 3;
「ここから東南《たつみ》の方、七百里に、一つの国がある。烏戈国《うかこく》とい
て、国王は兀突骨《ごつとつこつ》という者です。五穀を食《は》まず、火食せず、猛獣
|蛇魚《だぎょ》を喰い、身には鱗《うろこ》が生えているとか聞きます。また、彼の手
下には、藤甲軍《とうこうぐん》と呼ぶ兵が約三万はおりましょう」
「なるほど、それでは無敵だろう。ひとつ兀突骨《ごつとつこつ》に会ってこの急場を
んでみよう」
議にも及ばず、兀突骨は「よろしい」と大きくうなずいた。即座に三万の部下は藤甲
着こんで、洞市《どうし》に集まった。
検索はできたけど、インデックスは
きちんと使っているのか?
19.
EXPLAIN 結果
test=# EXPLAINANALYZE VERBOSE SELECT data FROM sangokushi WHERE data LIKE '%
兀突骨 %' LIMIT 3;
Limit (cost=100.00..128.29 rows=1 width=32) (actual time=0.516..0.518 rows=3
loops=1)
Output: data
-> Foreign Scan on public.sangokushi (cost=100.00..128.29 rows=1
width=32) (actual time=0.515..0.515 rows=3 loops=1)
Output: data
Remote SQL: SELECT data FROM public.sangokushi WHERE ((data ~~ '% 兀突
骨 %'::text))
Planning time: 0.091 ms
Execution time: 0.821 ms
リモート側に条件は渡されている
20.
リモート側の auto_explain 結果
LOG:duration: 0.040 ms plan:
Query Text: DECLARE c1 CURSOR FOR
SELECT data FROM public.sangokushi WHERE ((data ~~ '% 兀突骨 %'::text))
Bitmap Heap Scan on sangokushi (cost=14.03..21.81 rows=4 width=148)
Recheck Cond: (data ~~ '% 兀突骨 %'::text)
-> Bitmap Index Scan on meros_gin (cost=0.00..14.03 rows=4 width=0)
Index Cond: (data ~~ '% 兀突骨 %'::text)
リモート側で pg_bigm の
全文検索インデックスを使った
クエリが実行されている。
ローカルな問い合わせなら
btree 式インデックスも
gin インデックスも使える。
bar=#EXPLAIN SELECT * FROM test WHERE data->>'id' = '10000';
QUERY PLAN
-------------------------------------------------------------------------
Index Scan using test_id_idx on test (cost=0.42..8.44 rows=1 width=70)
Index Cond: ((data ->> 'id'::text) = '10000'::text)
(2 rows)
bar=# EXPLAIN SELECT * FROM test WHERE data @> '{"id":10000}';
QUERY PLAN
--------------------------------------------------------------------------
Bitmap Heap Scan on test (cost=28.77..336.47 rows=100 width=70)
Recheck Cond: (data @> '{"id": 10000}'::jsonb)
-> Bitmap Index Scan on test_idx (cost=0.00..28.75 rows=100 width=0)
Index Cond: (data @> '{"id": 10000}'::jsonb)
(4 rows)
あからさまにインデックス検索なのだ!
@> 演算子 {キー : 値 } の場合
WHERE 句を pushdown して、
リモート側でも GIN インデックスを使用
foo=# EXPLAIN ANALYZE SELECT * FROM test WHERE data @> '{"id":10000}';
QUERY PLAN
--------------------------------------------------------------
Foreign Scan on test (cost=100.00..128.29 rows=1 width=32)
(actual time=0.579..0.579 rows=1 loops=1)
Planning time: 0.052 ms
Execution time: 0.867 ms
(3 rows)
Time: 1.204 ms
外部テーブルから返却された時点で
1件になっていることに注目重点!
実際速い!
32.
->>' キー '演算子 値 の場合
WHERE 句は pushdown されず、
リモート側でフルスキャン全件取得!
アイエエエ!フルスキャン!
フルスキャンナンデ!
foo=# EXPLAIN ANALYZE SELECT * FROM test WHERE data->>'id' = '10000';
QUERY PLAN
----------------------------------------------------------------------
Foreign Scan on test (cost=100.00..159.93 rows=7 width=32)
(actual time=31.028..273.480 rows=1 loops=1)
Filter: ((data ->> 'id'::text) = '10000'::text)
Rows Removed by Filter: 99999
Planning time: 0.046 ms
Execution time: 273.581 ms
(5 rows)
そして外部テーブルからは全件 (10 万件 ) 返却されている!
あからさまにフルスキャンなのだ!ヤンナルネ・・・
実際遅い!