2016-05-21 14 views
0

Ich benutze Postgres 9.4. Dies ist meine Tabelle:Postgres scheint den falschen Index zu verwenden?

         Table "public.frontend_prescription" 
     Column  |   Type   |        Modifiers 
-------------------+-------------------------+-------------------------------------------------------------------- 
id    | integer     | not null default nextval('frontend_prescription_id_seq'::regclass) 
presentation_code | character varying(15) | not null 
total_items  | integer     | not null 
processing_date | date     | not null 
practice_id  | character varying(6) | not null 
Indexes: 
    "frontend_prescription_pkey" PRIMARY KEY, btree (id) 
    "frontend_prescription_6ea07fe3" btree (practice_id) 
    "frontend_prescription_by_practice" btree (presentation_code, practice_id) 
    "frontend_prescription_by_practice_and_code" btree (practice_id, presentation_code varchar_pattern_ops) 
    "frontend_prescription_idx_date_and_code" btree (processing_date, presentation_code) 

Dies ist meine Frage:

EXPLAIN (analyse, verbose) 
SELECT SUM(total_items) AS items, SUM(total_items) AS numerator 
FROM frontend_prescription 
WHERE ((presentation_code LIKE '0601012Z0%') OR (presentation_code LIKE '0601012X0%') OR (presentation_code LIKE '0601012V0%')) 
AND (practice_id='A81001') 
AND (processing_date='2016-01-01') 

Dies ist die Ausgabe:

Aggregate (cost=12.26..12.27 rows=1 width=4) (actual time=16898.277..16898.277 rows=1 loops=1) 
    Output: sum(total_items), sum(total_items) 
    -> Index Scan using frontend_prescription_idx_date_and_code on public.frontend_prescription (cost=0.57..12.26 rows=1 width=4) (actual time=9220.091..16898.251 rows=6 loops=1) 
     Output: id, presentation_code, presentation_name, total_items, net_cost, actual_cost, quantity, processing_date, price_per_unit, chemical_id, pct_id, practice_id, sha_id 
     Index Cond: (frontend_prescription.processing_date = '2016-01-01'::date) 
     Filter: (((frontend_prescription.practice_id)::text = 'A81001'::text) AND (((frontend_prescription.presentation_code)::text ~~ '0601012Z0%'::text) OR ((frontend_prescription.presentation_code)::text ~~ '0601012X0%'::text) OR ((frontend_prescription.presentation_code)::text ~~ '0601012V0%'::text))) 
     Rows Removed by Filter: 10036400 
Planning time: 6.054 ms 
Execution time: 16898.366 ms 

Hier ist die link to the explain.

Kann jemand vorschlagen, wie ich diese Abfragen beschleunigen könnte? Ich verstehe nicht wirklich, warum Postgres den frontend_prescription_idx_date_and_code Index benutzt, wenn der frontend_prescription_by_practice_and_code Index eine varchar Option hat, die Dinge schneller machen sollte.

Vielleicht würde es helfen, wenn ich einen dreispaltigen Index erstellen würde?

+0

Sie möchten einen Index für alle drei Spalten (Datum, Übungs_ID, Code). – Thilo

+1

Sie könnten dies vielleicht auch beschleunigen, indem Sie einen Bereich für den Code hinzufügen: 'AND presentation_code zwischen '0601012' und '0601013''. – Thilo

Antwort

1

Für diese Abfrage:

SELECT SUM(total_items) AS items, SUM(total_items) AS numerator 
FROM frontend_prescription 
WHERE ((presentation_code LIKE '0601012Z0%') OR (presentation_code LIKE '0601012X0%') OR (presentation_code LIKE '0601012V0%') 
     ) AND 
     (practice_id = 'A81001') AND 
     (processing_date = '2016-01-01'); 

Der beste Index ist ein Composite-Index auf frontend_prescription(practice_id, processing_date, presentation_code, total_items). Die letzte Spalte ist nicht unbedingt notwendig. Es macht den Index zu einem Deckungsindex für die Abfrage; Mit anderen Worten, alle für die Abfrage benötigten Informationen befinden sich im Index, sodass die Datenseiten nicht erforderlich sind.

Die ersten beiden Spalten können in beliebiger Reihenfolge sein, da die where-Klausel Gleichheit verwendet.

+0

vielen Dank! Wenn ich eine "LIKE" -Abfrage habe, wäre es sinnvoll, 'varchar_ops' zu verwenden, also' index myindex auf frontend_prescription zu erstellen (proceed_id, processing_date, presentation_code varchar_pattern_ops, total_items) '? – Richard

Verwandte Themen