3

フォームのクエリがあります

select sum(acol)
where xpath_exists('/Root/KeyValue[Key="val"]/Value//text()', xmlcol)

where句を高速化するために構築できるインデックスはどれですか?

を使用して作成された btree インデックス

create index idx_01 using btree(xpath_exists('/Root/KeyValue[Key="val"]/Value//text()', xmlcol))

は全く使われていないようです。

編集

に設定enable_seqscanするoffと、 を使用したクエリxpath_existsがはるかに高速になり (1 桁)、対応するインデックス ( で構築された btree インデックス) の使用が明確に示されxpath_existsます。

PostgreSQL がインデックスを使用せず、より遅いシーケンシャル スキャンを試みる理由の手がかりはありますか?

シーケンシャル スキャンをグローバルに無効にしたくないので、振り出しに戻ります。喜んで提案を歓迎します。

EDIT 2 - 計画の説明

以下を参照してください - 最初のプラン (seqscan オフ) のコストはわずかに高くなりますが、処理時間ははるかに高速です

b2box=# set enable_seqscan=off;
SET
b2box=# explain analyze
Select count(*) 
from B2HEAD.item
where cluster = 'B2BOX' and (  ( xpath_exists('/MessageInfo[FinalRecipient="ABigBank"]//text()', content) )  )  offset 0 limit 1;
                                                                           QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=22766.63..22766.64 rows=1 width=0) (actual time=606.042..606.042 rows=1 loops=1)
   ->  Aggregate  (cost=22766.63..22766.64 rows=1 width=0) (actual time=606.039..606.039 rows=1 loops=1)
         ->  Bitmap Heap Scan on item  (cost=1058.65..22701.38 rows=26102 width=0) (actual time=3.290..603.823 rows=4085 loops=1)
               Filter: (xpath_exists('/MessageInfo[FinalRecipient="ABigBank"]//text()'::text, content, '{}'::text[]) AND ((cluster)::text = 'B2BOX'::text))
               ->  Bitmap Index Scan on item_counter_01  (cost=0.00..1052.13 rows=56515 width=0) (actual time=2.283..2.283 rows=4085 loops=1)
                     Index Cond: (xpath_exists('/MessageInfo[FinalRecipient="ABigBank"]//text()'::text, content, '{}'::text[]) = true)
 Total runtime: 606.136 ms
(7 rows)

Explain.depesz.com の計画

b2box=# set enable_seqscan=on;
SET
b2box=# explain analyze
Select count(*) 
from B2HEAD.item
where cluster = 'B2BOX' and (  ( xpath_exists('/MessageInfo[FinalRecipient="ABigBank"]//text()', content) )  )  offset 0 limit 1;
                                                                           QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=22555.71..22555.72 rows=1 width=0) (actual time=10864.163..10864.163 rows=1 loops=1)
   ->  Aggregate  (cost=22555.71..22555.72 rows=1 width=0) (actual time=10864.160..10864.160 rows=1 loops=1)
         ->  Seq Scan on item  (cost=0.00..22490.45 rows=26102 width=0) (actual time=33.574..10861.672 rows=4085 loops=1)
               Filter: (xpath_exists('/MessageInfo[FinalRecipient="ABigBank"]//text()'::text, content, '{}'::text[]) AND ((cluster)::text = 'B2BOX'::text))
               Rows Removed by Filter: 108945
 Total runtime: 10864.242 ms
(6 rows)

Explain.depesz.com の計画

4

1 に答える 1

4

プランナーのコスト パラメータ

最初のプラン (seqscan オフ) のコストはわずかに高くなりますが、処理時間ははるかに高速です

これは、あなたのrandom_page_costandseq_page_costがおそらく間違っていることを示しています。ほとんどのデータベースが RAM にキャッシュされているか、SSD、キャッシュ付き SAN、またはランダム I/O が本質的に高速なその他のストレージを使用しているため、高速ランダム I/O を備えたストレージを使用している可能性があります。

試す:

SET random_page_cost = 1;
SET seq_page_cost = 1.1;

コストパラメータの差を大幅に減らしてから再実行します。それがうまくいく場合は、これらのパラメーターを変更することを検討してpostgresql.conf.ください。

行数の見積もりは合理的であるため、プランナーの見積もりミスの問題やテーブル統計の問題ではないようです。

不適切なクエリ

あなたの質問も間違っています。OFFSET 0 LIMIT 1を使用しないORDER BYと、正確に 1 つの一致が保証されない限り、予測できない結果が生成されます。この場合、OFFSET ... LIMIT ...句は不要であり、完全に削除できます。

SELECT max(...)通常は、可能な限り、またはSELECT min(...)可能な限り、そのようなクエリを表現する方がはるかに優れています。PostgreSQL は、インデックスを使用して、高価なテーブル スキャンやインデックス スキャンとソートを実行せずに、目的の値を抜き取ることができる傾向があります。

チップ

ところで、今後の質問については、PostgreSQL wiki にパフォーマンス カテゴリに関する優れた情報と、スロー クエリの質問をするためのガイドがあります。

于 2013-04-19T01:24:17.233 に答える