Ich habe eine Tabelle mit 50.000 Zeilen. Es ist eigentlich eine PostGIS-Tabelle.
Die Abfrage besteht aus 4 Teilen (1 obligatorisch) (3 optional)
- Kreuzungsfeld (ein geografisches Rechteck) mit 4 Lat, lang (ich verwende st_intersects) [Obligatorisch]
- Datumsbereich (min, max) in einem Datumsfeld
- Der Dateityp (ein Satz von bis zu 8 Textwerten) verwendet derzeit IN (.....), aber ich kann dies bei Bedarf zu einer temporären Tabelle machen. Ich sehe, dass viele Leute IN nicht mögen.
- Land (ein Textwert).
Ich erwarte ungefähr 100 - 4.000 zurückgegebene Zeilen
Wenn ich einen zusammengesetzten Index für die Tabelle erstelle, welche Spalte sollte ich zuerst verwenden. Die Feinkörnigkeit ist wahrscheinlich der Standort (Daten sind über die ganze Welt verteilt). Ich habe es derzeit als GIST-Index.
Die anderen Indizes wären BTREE.
Meine Intuition sagt, verwenden Sie feinkörnig und natürlich zuletzt. ZB gibt es nur ungefähr 12 Dateitypen, das wären also sehr große Buckets für den Index.
Was sagen die PostgreSQL- und PostGIS-Gurus (die die Interna des Systems kennen)?
AKTUALISIEREN:
Lassen Sie mich diese Frage schärfen.
- Ich möchte nicht, dass jemand die Arbeit machen muss, die ich machen sollte. Ich respektiere deine Zeit zu sehr. Also werde ich später zur Erklärungsanalyse kommen.
- Ich suchte nur nach Hinweisen, Tipps und Richtlinien.
- Ich habe diesen ausgezeichneten kleinen Beitrag gelesen: https://devcenter.heroku.com/articles/postgresql-indexes#managing-and-maintaining-indexes über Indizes
- Normalerweise erstelle ich 4 separate Indizes (Geobox, Ländername, Dateityp und Datum), möchte aber sehen, was eine zusammengesetzte Abfrage bewirken würde.
Sagen Sie mir, ob eine dieser Annahmen falsch ist. (Ich bin ziemlich neu in der Idee von zusammengesetzten Indizes)
- Ordnung ist wichtig. Wählen Sie als ersten Index den Index, der die Zeilen am meisten abschneidet (in meinem Fall ist die Position (Geografie), bei der es sich um ein einfaches Polygon oder ein Multipolygon handelt, am besten geeignet).
- Manchmal überspringen Abfragen Indizes. Wenn ich jedoch eine zusammengesetzte Abfrage mit dem Schlüssel (Nr. 1, Nr. 2, Nr. 3, Nr. 4) erstelle, verwendet der Planer auch dann die einzelne zusammengesetzte Abfrage, wenn er nach Nr. 1, Nr. 3 fragt ist gewartet.
- Normalerweise würde ich drei BTREE-Abfragen und eine GIST (für den Geografietyp) erstellen. PostGIS unterstützt nicht das Erstellen einer Verbindung aus mehreren Indextypen. Also muss ich den zusammengesetzten Index GIST verwenden. Aber das sollte nicht schaden.
- Wenn ich zusätzliche zusammengesetzte oder Einzelwertindizes erstelle, ist der Planer klug genug, um den intelligentesten auszuwählen .....
- Der Ländername kann ungefähr 250 verschiedene Werte haben und ist offensichtlich stark mit dem Standort (Geobox) verbunden. Wenn der nächstbeste Index zum Reduzieren der Zeilengröße jedoch Dateityp ist, sollte ich diesen als nächstes verwenden. Ich erwarte nicht, dass die Benutzer häufig Land oder Datum in ihren Abfragesätzen verwenden.
- Ich muss mich NICHT darum kümmern, einen zusammengesetzten Index mit 4 Schlüsseln zu erstellen, um die Größe der Indexdaten erheblich zu erhöhen. Das heißt, wenn ein Ein-Schlüssel-Index 90% der Leistungssteigerung ausmachen würde, schadet es nicht, 3 weitere Elemente hinzuzufügen, um ihn zusammenzusetzen. Umgekehrt sollte ich wirklich beide Indizes erstellen. Ein einzelner geografischer Index sowie ein zusammengesetzter Index. Lassen Sie den Planer herausfinden, welcher am besten ist, und berücksichtigen Sie dabei die Größe der Indextabelle.
Auch hier bitte ich niemanden, meine Lösung zu entwerfen, ich mache mir keine Gedanken über die Arbeit anderer. Aber ich brauche Dinge, die mir die PostGreSQL-Dokumentation nicht über die Implementierung sagt
[Der Grund, warum ich noch kein EXPLAIN-Ergebnis anzeigen kann, ist, dass ich diese 25K-Zeilentabelle aus einer 24M-Zeilentabelle erstellen muss. Es dauert länger als ich dachte. Ich gruppiere Dinge in 1.000 Elementgruppen und lasse den Benutzer die 25K-Zeilentabelle abfragen. Aber meine nächste Frage wird beinhalten, die Ergebnisse dieser Abfrage zu verwenden, um zur MASTER 25M-Zeilentabelle zu gehen und Dinge herauszuholen, und hier wird die Leistung des zusammengesetzten Index wirklich HIT].
Beispielabfrage unten:
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-Ergebnisse (Ich habe keine zusammengesetzten Indizes eingegeben, und von der Geschwindigkeit, die ich sehe, weiß ich nicht, ob ich muss).
"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
für die Abfrage.