2017-06-08 4 views
0

Ich bin sehr seltsames Verhalten der Postgres Abfrage konfrontiert. Ich habe eine Tabelle "p_MyTable", die eine Partition einer anderen Tabelle ist. „P_MyTable“ hat rund 600 Millionen Platten und hat den Index,Postgres Abfrage verwendet nicht Index

CREATE INDEX idx_p_MyTable_id ON MySchema.p_MyTable USING btree(IndColumn); 

Wenn ich die folgende Abfrage ausführen es in kürzester Zeit läuft und Ergebnis liefert sehr schnell. Dies ist der Abfrage- und Erläuterungsplan.

explain select max(IndColumn) from MySchema.p_MyTable ms where ent_attr_97='ABC' and ent_attr_96='EFG' and ent_attr_98='HIJ' 
and ent_date_2::date <= '2017-06-01 00:00:00'::date 

"Result (cost=4.85..4.86 rows=1 width=0)" 
" InitPlan 1 (returns $0)" 
" -> Limit (cost=0.57..4.85 rows=1 width=8)" 
"   -> Index Scan Backward using idx_p_MyTable_id on p_MyTable ms (cost=0.57..727648341.49 rows=169996075 width=8)" 
"    Index Cond: (IndColumn IS NOT NULL)" 
"    Filter: ((ent_attr_97 = 'ABC'::text) AND (ent_attr_96 = 'EFG'::text) AND (ent_attr_98 = 'HIJ'::text) AND ((ent_date_2)::date <= '2017-06-01'::date))" 

Es funktioniert für die Aggregatfunktion "min" auch auf die gleiche Weise. Aber wenn ich für andere Funktionen versuche, ändert sich der EXPLAIN-Plan und die Abfrage wird nicht in vielen Minuten ausgeführt.

explain select count(IndColumn) from MySchema.p_MyTable ms where ent_attr_97='ABC' and ent_attr_96='EFG' and ent_attr_98='HIJ' 
and ent_date_2::date <= '2017-06-01 00:00:00'::date 

"Aggregate (cost=53319339.50..53319339.51 rows=1 width=8)" 
" -> Bitmap Heap Scan on p_MyTable ms (cost=11209851.27..52894349.31 rows=169996075 width=8)" 
"  Recheck Cond: (ent_attr_96 = 'EFG'::text)" 
"  Filter: ((ent_attr_97 = 'ABC'::text) AND (ent_attr_98 = 'HIJ'::text) AND ((ent_date_2)::date <= '2017-06-01'::date))" 
"  -> Bitmap Index Scan on p_MyTable_comp (cost=0.00..11167352.25 rows=509988224 width=0)" 
"    Index Cond: (ent_attr_96 = 'EFG'::text)" 

explain select distinct (IndColumn) from MySchema.p_MyTable ms where ent_attr_97='ABC' and ent_attr_96='EFG' and ent_attr_98='HIJ' 
and ent_date_2::date <= '2017-06-01 00:00:00'::date 

"HashAggregate (cost=53319339.50..53319339.71 rows=21 width=8)" 
" Group Key: IndColumn" 
" -> Bitmap Heap Scan on p_MyTable ms (cost=11209851.27..52894349.31 rows=169996075 width=8)" 
"  Recheck Cond: (ent_attr_96 = 'EFG'::text)" 
"  Filter: ((ent_attr_97 = 'ABC'::text) AND (ent_attr_98 = 'HIJ'::text) AND ((ent_date_2)::date <= '2017-06-01'::date))" 
"  -> Bitmap Index Scan on p_MyTable_comp (cost=0.00..11167352.25 rows=509988224 width=0)" 
"    Index Cond: (ent_attr_96 = 'EFG'::text)" 

explain select avg (IndColumn) from MySchema.p_MyTable ms where ent_attr_97='ABC' and ent_attr_96='EFG' and ent_attr_98='HIJ' 
and ent_date_2::date <= '2017-06-01 00:00:00'::date 

"Aggregate (cost=53319339.50..53319339.51 rows=1 width=8)" 
" -> Bitmap Heap Scan on p_MyTable ms (cost=11209851.27..52894349.31 rows=169996075 width=8)" 
"  Recheck Cond: (ent_attr_96 = 'EFG'::text)" 
"  Filter: ((ent_attr_97 = 'ABC'::text) AND (ent_attr_98 = 'HIJ'::text) AND ((ent_date_2)::date <= '2017-06-01'::date))" 
"  -> Bitmap Index Scan on p_MyTable_comp (cost=0.00..11167352.25 rows=509988224 width=0)" 
"    Index Cond: (ent_attr_96 = 'EFG'::text)" 

Bitte erklären Sie mir, warum die Änderungen erklären vollständig, wie ich denke, wenn max/min-Index verwenden richtig, dann sollte es auch für andere Funktionen arbeiten.

Vielen Dank im Voraus.

+0

Ich habe überprüft, Tabelle wird vor kurzem gesaugt und analysiert. – sand

Antwort

0

Indizes werden (meistens) entweder für "where" Bedingungen oder zur Sortierung ("order by") verwendet. (auch Indizes können für viele andere Dinge verwendet werden, aber für diesen Fall wird es helfen, sie auf die Fälle zu beschränken)

Die „max (IndColumn)“ ist irreführend, da die Abfrage wie folgt umgeschrieben wird:

select IndColumn 
from MySchema.p_MyTable ms 
where ent_attr_97='ABC' and ent_attr_96='EFG' and ent_attr_98='HIJ' 
and ent_date_2::date <= '2017-06-01 00:00:00'::date 
AND IndColumn is not null 
ORDER by IndColumn desc 
LIMIT 1 

So wird der Index für "AND IndColumn ist nicht null ORDER by IndColumn desc" verwendet.

Für Ihre weiteren Fragen würden Sie Indizes für die Spalten müssen in "where", So etwas wie

CREATE INDEX idx_p_foo ON MySchema.p_MyTable USING btree(ent_attr_96, ent_attr_97, ent_attr_98); 

helfen könnte. Angenommen, Sie haben viele Abfragen, die diese 3 Spalten verwenden.

Sie können auch das Datum hinzufügen. Obwohl ich nicht sicher bin, dass dies viel helfen wird, da es nur ein Enddatum ist, ohne Beginn gegeben. Also nicht sicher, ob der Abfrageplaner das Datum im Index verwenden wird. Und wenn ja, ist die Frage, wie viele Zeilen nach dem Datum gefiltert werden, lohnt es sich, die Indexgröße zu erhöhen?

Verwandte Themen