2016-05-21 5 views
0

私はPostgres 9.4を使用しています。これが私のテーブルです:Postgresが間違ったインデックスを使用しているようですか?

         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) 

これが私のクエリです:

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') 

これが出力されます。ここでは

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 

link to the explainです。

誰も私がどのようにこれらの質問をスピードアップするかもしれないか提案できますか? frontend_prescription_by_practice_and_codeインデックスにvarcharオプションがあるとPostgresがなぜfrontend_prescription_idx_date_and_codeインデックスを使用しているのか分かりません。

おそらく、私が3列のインデックスを作成した場合、それは役に立ちますか?このクエリの

+0

3つの列(date、practice_id、code)すべてに対してインデックスが必要です。 – Thilo

+1

また、コードに範囲を追加することでこれをスピードアップすることもできます: 'AND60_061012 'と' 0601013'_の間のプレゼンテーションコード。 – Thilo

答えて

1

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'); 

最良の指標はfrontend_prescription(practice_id, processing_date, presentation_code, total_items)上の複合インデックスです。最後の列は厳密には必要ではありません。これは、索引を照会のカバリング索引にします。つまり、クエリに必要なすべての情報がインデックスにあるため、データページは必要ありません。

where句には等価が使用されているため、最初の2つの列はどちらの順序でも構いません。

+0

ありがとう!私は 'LIKE'クエリを持っているので、' varchar_ops'を使用すると意味がありますので、 'frontend_prescription(practice_id、processing_date、presentation_code varchar_pattern_ops、total_items)にインデックスmyindexを作成します'? – Richard

関連する問題