Ich habe eine Master/Detail-Tabelle Situation. Für jeden Eintrag am Stammtisch habe ich Dutzende an der Detailtabelle.Patial Index basiert auf Daten der zweiten Tabelle
Können sagen, das ist meine Tabellen sind:
+-----------------------
| Master
+-----------------------
| master_key integer,
| insert_date timestamp
+-----------------------
+-----------------------
| Detail
+-----------------------
| detail_key integer,
| master_key integer
| quantity numeric
| amount numeric
+-----------------------
Und meine am meisten verwendete Abfrage ist so etwas wie
SELECT extract(year from insert_date) AS Insert_Year, extract(month from insert_date) AS Insert_Month, sum(quantity) AS Quantity, sum(amount) AS Amount
FROM Master, Detail
WHERE (amount not null) and (insert_date <= '2016-12-31') and (insert_date >= '2015-01-01') and (Detail.master_key=Master.master_key)
GROUP BY Insert_Year, Insert_Month
ORDER BY Insert_Year ASC, Insert_Month ASC;
Diese Abfrage zu verlangsamen wird, weil es Tonnen von Daten für viele Jahre ist in beiden Tabellen .
Natürlich habe ich Indizes an beiden Tabellen und EXPLAIN ANALYZE
sagt mir, dass der INDEX-Scan-Modus als 80% der Loch-Ausführungszeit dauert.
"Sort (cost=44013.52..44013.53 rows=1 width=19) (actual time=17073.129..17073.129 rows=16 loops=1)"
" Sort Key: (date_part('year'::text, master.insert_date)), (date_part('month'::text, master.insert_date))"
" Sort Method: quicksort Memory: 26kB"
" -> HashAggregate (cost=44013.49..44013.51 rows=1 width=19) (actual time=17073.046..17073.053 rows=16 loops=1)"
" Group Key: date_part('year'::text, master.insert_date), date_part('month'::text, master.insert_date)"
" -> Nested Loop (cost=0.43..43860.32 rows=15317 width=19) (actual time=0.056..15951.178 rows=843647 loops=1)"
" -> Seq Scan on master (cost=0.00..18881.38 rows=3127 width=12) (actual time=0.027..636.202 rows=182338 loops=1)"
" Filter: ((date(insert_date) >= '2015-01-01'::date) AND (date(insert_date) <= '2016-12-31'::date))"
" Rows Removed by Filter: 443031"
" -> Index Scan using idx_detail_master_key on detail (cost=0.43..7.89 rows=7 width=15) (actual time=0.055..0.077 rows=5 loops=182338)"
" Index Cond: (master_key = master.master_key)"
" Filter: (amount IS NOT NULL)"
" Rows Removed by Filter: 2"
"Planning time: 105.317 ms"
"Execution time: 17073.396 ms"
Also meine Idee war, die Indexgrößen zu reduzieren, indem Sie sie teilweise definieren. In den meisten Fällen werden nur Daten der letzten 2 Jahre abgefragt.
Also habe ich versucht, so etwas wie das:
CREATE INDEX idx_detail_table_master_keys
ON detail (master_key)
WHERE master_key in (SELECT master_key FROM master WHERE (extract(year from insert_date) = 2016) or (extract(year from insert_date) = 2015))
Der Grund hierfür ist es nicht die endgültige Version sollte nur ein Proof of Concept und es ist fehlgeschlagen. PGAdmin Sagt mir, dass ich keine Subselects für die Indexerstellung verwenden darf.
Meine Frage ist also: Ist es möglich, einen partiellen Index zu erstellen, basierend auf den Daten einer anderen Tabelle?
Und natürlich wäre ich dankbar für irgendwelche Tipps, die Konstellationen wie diese beschleunigen.
Bezug
[Bearbeiten] Ihre Frage ein und fügen Sie die Ausgabe von ': Eine ausführlichere Beschreibung zu diesen Themen finden Sie hier erklären (analysieren, verbose) 'für Ihre Abfrage. Nicht verwandt, aber: Sie sollten wirklich beginnen, einen expliziten 'JOIN'-Operator anstelle des alten, veralteten impliziten Joins in der' Where'-Klausel zu verwenden. –
@a_horse_with_no_name: Ich musste die Detailtabelle und die Abfrage deaktivieren, um sie an das EXPLAIN-Ergebnis anzupassen. Aber es ist getan;). Die Idee dieser Frage ist nicht nur meine aktuelle Abfrage zu verbessern, sondern zu lernen, wie ich ähnliche Konstrukte im Allgemeinen beschleunigen kann. Deshalb habe ich versucht, es so weit wie möglich zu vereinfachen. – Mike
@Mike Versuchen Sie eher, Index für 'Datum (Einfügedatum)' wie 'CREATE INDEX IDX_detail_table_master_insert ON Master USING btree (Datum (Einfügung_Datum)) zu erstellen –