5万行のテーブルがあります。これは実際にはPostGISテーブルです。
クエリには4つの部分があります(1つは必須)(3つはオプション)
- 緯度と経度が4の交差ボックス(地理長方形)(st_intersectsを使用)[必須]
- 日付フィールドの日付範囲(最小、最大)
- 現在IN(.....)を使用しているファイルタイプ(最大8つのテキスト値のセット)ですが、必要に応じて一時テーブルにすることができます。INが嫌いな人が多いようです。
- 国(テキスト値)。
返される行は約100〜4,000になると思います
テーブルに複合インデックスを作成する場合、最初にどの列を使用する必要がありますか。きめ細かいのはおそらく場所です(データは世界中に広がっています)。現在、GISTインデックスとして持っています。
他のインデックスはBTREEです。
私の直感は、きめ細かい、そして最後にコースを使用すると言います。たとえば、ファイルタイプは約12しかないため、インデックスのバケットは非常に大きくなります。
PostgreSQLとPostGISの達人(システムの内部を知っている人)は何と言っていますか?
更新:
この質問をもっとはっきりさせましょう。
- やるべきことを誰かにやらせてもらいたくない。あなたの時間を尊重しすぎます。ですから、後で説明の分析に行きます。
- 私が探していたのは、いくつかの指針とヒント、およびガイドラインだけでした。
- 私はこの優れた小さな投稿を読みました:https : //devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexesインデックスについて
- 私が通常行うことは、4つの個別のインデックス(ジオボックス、国名、file_type、および日付)を作成することですが、複合クエリが何を行うかを確認したいのです。
これらの仮定のいずれかが間違っているかどうか教えてください。(私は複合インデックスのアイデアにかなり新しいです)
- 順序は重要です。最初のインデックスとして、行を最も削減するインデックスを選択します(私の場合、場所(地理)は単純なポリゴンまたはマルチポリゴンが最も効果的です)。
- クエリはインデックスをスキップすることがあります。しかし、キー(#1、#2、#3、#4)を使用して複合クエリを作成した場合、ユーザーが#1、#3を要求するものを作成した場合でも、プランナーは単一の複合クエリを使用します。維持されている。
- 通常、3つのBTREEクエリと1つのGIST(地理タイプ用)を作成します。PostGISは、複数のインデックスタイプからの複合の作成をサポートしていません。したがって、GISTを複合インデックスとして使用する必要があります。しかし、それは物事を傷つけるべきではありません。
- 追加の複合インデックスまたは単一値インデックスを作成する場合、プランナーは最もインテリジェントなインデックスを選択するのに十分スマートです。
- 国名は約250の異なる値を持つことができ、明らかに場所(ジオボックス)に強くリンクされていますが、行サイズを削減するための次善のインデックスがfile_typeの場合は、次に使用する必要があります。ユーザーがクエリセットで国や日付を頻繁に使用するとは思わない。
- 4つのキーの複合インデックスを作成すると、インデックスデータのサイズが大幅に増加することを心配する必要はありません。つまり、1つのキーのインデックスがパフォーマンス向上の90%になる場合でも、さらに3つの項目を追加して複合させることは問題ありません。逆に、実際には両方のインデックスを作成する必要があります。単一の地理インデックスと複合インデックス。プランナーにどちらが最適かを判断させ、インデックステーブルのサイズを考慮します。
繰り返しになりますが、私は誰かに私のソリューションを設計するように頼んでいません。しかし、PostGreSQLドキュメントが実装について教えてくれないことが必要です
[まだEXPLAIN結果を表示できないのは、24Mの行テーブルからこの25Kの行テーブルを作成する必要があるためです。思ったより時間がかかります。私はものを1,000個のアイテムグループにクラスター化し、ユーザーに25K行テーブルに対してクエリを実行させています。しかし、次の質問では、そのクエリの結果を使用してMASTER 25M行テーブルに移動し、物事を引き出します。これが、複合インデックスのパフォーマンスが実際にHITになる場所です。
以下のサンプルクエリ:
SELECT
public.product_list_meta_mv.cntry_name AS country,
public.product_list_meta_mv.product_producer AS producer,
public.product_list_meta_mv.product_name AS prod_name,
public.product_list_meta_mv.product_type AS ptype,
public.product_list_meta_mv.product_size AS size,
ST_AsGeoJSON(public.product_list_meta_mv.the_geom, 10, 2) AS outline
FROM
public.product_list_meta_mv
WHERE
public.product_list_meta_mv.cntry_name = 'Poland'
AND
ST_Intersects(public.product_list_meta_mv.the_geom,
st_geogfromtext('SRID=4326;POLYGON((21.23107910156250 51.41601562500000,
18.64379882812500 51.41601562500000,
18.64379882812500 48.69415283203130,
21.23107910156250 48.69415283203130,
21.23107910156250 51.41601562500000))'))
AND (date >= '1/2/1900 5:00:00 AM'
AND date <= '2/26/2014 10:26:44 PM')
AND (public.product_list_meta_mv.product_type in
('CIB10','DTED0','DTED1','DTED2','CIB01','CIB05')) ;
EXPLAIN ANALYZEの結果(複合インデックスを入れなかったため、表示されている速度から、必要かどうかわかりません)。
"Bitmap Heap Scan on catalog_full cat (cost=4.33..37.49 rows=1 width=7428) (actual time=1.147..38.051 rows=35 loops=1)"
" Recheck Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
" Filter: (((type)::text = ANY ('{CADRG,CIB10,DTED1,DTED2}'::text[])) AND (_st_distance('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography, outline, 0::double precision, false) < 1e-005::double precision))"
" Rows Removed by Filter: 61"
" -> Bitmap Index Scan on catalog_full_outline_idx (cost=0.00..4.33 rows=8 width=0) (actual time=0.401..0.401 rows=96 loops=1)"
" Index Cond: ('0103000020E61000000100000005000000000000005838354000000000AEB0494000000000A0A7324000000000AEB0494000000000A0A73240000000006C5D48400000000058383540000000006C5D4840000000005838354000000000AEB04940'::geography && outline)"
"Total runtime: 38.109 ms"
EXPLAIN ANALYZE SELECT pid,product_name,type,country,date,size,cocom,description,egpl_date,ST_AsGeoJSON(outline, 10, 2) AS outline
FROM portal.catalog_full AS cat
WHERE ST_Intersects(st_geogfromtext('SRID=4326;POLYGON((21.2200927734375 51.38031005859375, 18.65478515625 51.38031005859375, 18.65478515625 48.7298583984375, 21.2200927734375 48.7298583984375, 21.2200927734375 51.38031005859375))'), cat.outline)
AND (cat.type in ('CADRG','CIB10','DTED1','DTED2'))
EXPLAIN ANALYZE
クエリを表示します。