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'))
quelle
EXPLAIN ANALYZE
für die Abfrage.Antworten:
Als Teil meiner Arbeit pflege ich eine ziemlich große PostgreSQL-Datenbank (ca. 120 GB auf der Festplatte, mehrere Tabellen mit mehreren Millionen Zeilen) und habe einige Tricks gesammelt, wie die Abfragen beschleunigt werden können. Zunächst einige Kommentare zu Ihren Annahmen:
Ich würde vorschlagen, keinen 4-Wege-Index zu erstellen. Versuchen Sie, eine zu erstellen, und überprüfen Sie dann die Größe. Sie können sehr groß werden. Nach meiner Erfahrung waren vier 1-Schlüssel-Indizes fast so schnell wie ein einzelner 4-Wege-Index. Ein Trick, der für bestimmte Abfragen gut funktioniert, sind Teilindizes, dh etwa so:
CREATE INDEX ON table_x (Schlüssel1, Schlüssel2, Schlüssel3) WHERE some_x_column = 'XXXX';
Ich habe Aliase in meiner .psqlrc-Datei mit Abfragen erstellt, um herauszufinden, welche Indizes hinzugefügt oder entfernt werden sollen. Schauen Sie sich diese bei GitHub an: .psql
Ich benutze häufig: seq_scans und: bigtables und dann \ d table_name, um Details über die Tabelle zu erhalten. Vergessen Sie nicht, die Statistik zurückzusetzen, nachdem Sie einige Änderungen vorgenommen haben. Wählen Sie pg_stat_reset ().
quelle
Ich denke, das, was am wahrscheinlichsten hilft (wenn überhaupt), wäre, product_type als zweite Spalte zum Hauptindex hinzuzufügen. Aber ohne zu wissen, wie viele Zeilen mit jeder der UND-Bedingungen (isoliert) für Ihre typischen / problematischen Abfragen übereinstimmen, können wir nur raten.
Wenn ich mich dem nähere, führe ich als erstes die Abfrage in vereinfachter Form aus, wobei die WHERE-Klausel unter EXPLAIN ANALYZE nur eine Bedingung enthält, die jeweils nacheinander ausgeführt wird. Sehen Sie sich sowohl die geschätzten als auch die tatsächlichen Zeilen für jede Zeile an.
quelle