2

次のステートメントで、自分で修正できないという非常に深刻なパフォーマンスの問題があります。

与えられた状況

  • Postgis 1.4がインストールされたpostgres 8.4データベースがあります
  • 〜 900 万のエントリを持つ地理空間テーブルがあります。このテーブルには (postgis) ジオメトリ列と tsvector 列があります
  • ジオメトリに GIST インデックスがあり、vname 列に VNAME インデックスがあります
  • テーブルはANALYZE'd

to_tsqueryこれらのジオメトリのサブセット内でテキスト検索を実行すると、影響を受けるすべての ID が返されます。

検索する領域は、900 万のデータセットを約 100.000 に制限し、ts_queryこの領域内の結果セットは、0..1000 エントリの出力を与える可能性が最も高くなります。

問題

クエリ アナライザーは、最初に vname でビットマップ インデックス スキャンを実行することを決定し、次に集約してジオメトリにフィルターを適用します (および、このステートメントに含まれるその他の条件)。

クエリ アナライザーの出力:

Aggregate  (cost=12.35..12.62 rows=1 width=510) (actual time=5.616..5.616 rows=1 loops=1)
->  Bitmap Heap Scan on mxgeom g  (cost=8.33..12.35 rows=1 width=510) (actual time=5.567..5.567 rows=0 loops=1)
     Recheck Cond: (vname @@ '''hemer'' & ''hauptstrasse'':*'::tsquery)
     Filter: (active AND (geom && '0107000020E6100000010000000103000000010000000B0000002AFFFF5FD15B1E404AE254774BA8494096FBFF3F4CC11E40F37563BAA9A74940490200206BEC1E40466F209648A949404DF6FF1F53311F400C9623C206B2494024EBFF1F4F711F404C87835954BD4940C00000B0E7CA1E4071551679E0BD4940AD02004038991E40D35CC68418BE49408EF9FF5F297C1E404F8CFFCB5BBB4940A600006015541E40FAE6468054B8494015040060A33E1E4032E568902DAE49402AFFFF5FD15B1E404AE254774BA84940'::geometry) AND (mandator_id = ANY ('{257,1}'::bigint[])))
     ->  Bitmap Index Scan on gis_vname_idx  (cost=0.00..8.33 rows=1 width=0) (actual time=5.566..5.566 rows=0 loops=1)
           Index Cond: (vname @@ '''hemer'' & ''hauptstrasse'':*'::tsquery)

これにより、多くのI/Oが発生します-AFAIK最初にジオメトリを制限し、後でvname検索を行う方が賢明です。

試みられた解決策

目的の動作を達成するために、私はしようとしました

  1. 私はgeom @@AREAをサブセレクトに入れました->実行計画を変更しませんでした
  2. 目的の領域サブセットで一時ビューを作成しました -> 実行計画を変更しませんでした
  3. 目的の領域の一時テーブルを作成しました -> 作成に 4 ~ 6 秒かかり、さらに悪化しました。

ところで、実際のクエリを投稿していないことをお詫びします。投稿した場合、上司は本当に怒っていると思います。また、誰かが実際のクエリを修正するための理論的な指針をもっと探しています。さらに説明が必要な場合はお尋ねください


編集

widthリチャードは非常に良い点を持っていました.ステートメントを使用してクエリプランナーの望ましい動作を実現できます. 悪い点は、この一時テーブル (または CTE) が vname インデックスをめちゃくちゃにするため、場合によってはクエリが何も返さないことです。

を使用してオンザフライで新しい vname を作成することでこれを修正できましたto_tsvector()が、これは (あまりにも) コストがかかります - クエリごとに約 300 - 500 ミリ秒。

私の解決策

私は vname 検索を捨てて、単純なLIKE('%query_string%')(10-20 ミリ秒/クエリ) を使用しましたが、これは私の特定の環境でのみ高速です。YMMV。

4

1 に答える 1

2

tsvector の統計処理にいくつかの改善がありました (PostGIS もそうだと思いますが、私は使用していません)。時間があれば、9.1 リリースでもう一度試してみて、どうなるか見てみる価値があるかもしれません。

ただし、この 1 つのクエリについては、WITH コンストラクトを確認することをお勧めします。

http://www.postgresql.org/docs/8.4/static/queries-with.html

ジオメトリ部分を WITH 句として配置すると、最初に評価され (保証され)、その結果セットが次の SELECT によってフィルター処理されます。ただし、遅くなる可能性がありますが、試してみるまでわかりません。

work_mem の調整も役立つかもしれません。これはセッションごとに行うことができます ("SET work_mem = ...")。

http://www.postgresql.org/docs/8.4/static/runtime-config-resource.html#RUNTIME-CONFIG-RESOURCE-MEMORY

于 2011-11-18T16:37:28.207 に答える