2016-03-23 6 views
0
explain analyze SELECT COUNT(*) FROM "customers" WHERE (TRIM(telephone) = 
'06868787878' AND check_id = 41); 

          QUERY PLAN                  
------------------------------------------------------------------------------ 
------------------------------------------------------------------- 
Aggregate (cost=12982.58..12982.59 rows=1 width=0) (actual 
time=200.452..200.453 rows=1 loops=1) 
-> Bitmap Heap Scan on customers (cost=544.59..12982.21 rows=147 width=0) 
(actual time=14.555..200.447 rows=1 loops=1) 
    Recheck Cond: (check_id = 41) 
    Filter: (btrim((telephone)::text) = '06868787878'::text) 
    Rows Removed by Filter: 29394 
    -> Bitmap Index Scan on idx_customers_check_id (cost=0.00..544.55 
    rows=29350 width=0) (actual time=9.669..9.669 rows=29395 loops=1) 
      Index Cond: (check_id = 41) 
    Total runtime: 200.750 ms 
(8 rows) 

時にはその取り込み(293.6ms)、(1956.3ms)、これを避ける方法はありますか?postgresqlを頻繁に取る単一カウントクエリ

答えて

1

あなたのスキーマと使用パターンにかなり依存しますが、試してみるべきことがいくつかあります。

  1. このカウントを行うときではなく、DBに入力された電話番号を切り捨てます。カウント中にTRIMを使用すると、DBは評価しているすべての行でそれを実行する必要があり、無駄です。数字が常に切り詰められることを保証すれば、より簡単なtelephone = '06868787878'チェックを行うことができます。それが一般的な場合は、telephoneにインデックスがあることを確認してください。
  2. telephoneのデータをクエリの前にトリミングすることができない、またはしたくない場合は、create an index on the expressionTRIM(telephone)です。これにより、TRIMが行っているすべての作業が効果的に事前計算されますが、それだけでTRIM(telephone) = '123'を調べることは明らかです。telephone = '123'はそれ以上は役に立ちません。
  3. できるだけ特定の列にインデックスを置きます。例えば。 check_idが2行で41である場合、Postgresは最初にそのインデックスを使用してセットを絞り込むことができます。残りの条件を検証する作業はほとんどありません。 check_idが多くの場合41ですが、telephoneはまれにしか06868787878であり、同じことが適用され、インデックスはtelephoneになります。両方がかなり均等に分散されており、これが一般的なクエリパターンの場合は、を(check_id, telephone)に設定することをお勧めします。単一列インデックスの場合と同じ理由で、より具体的な列を最初に配置するか、列の1つだけでフィルタリングする必要がある場合は、最初に配置します。例えば。 (check_id, telephone)インデックスを使用すると、check_idプレフィックスも効率的にクエリできます。

    3b。 Postgresは、主レコードを取得するためにセカンダリルックアップを実行したり、インデックスでカバーされていない条件をチェックしたりすることなく、インデックスを使用してカウントを実行できるので、すべての条件をカバーするマルチカラムインデックスを作成することは非常に効率的です。

+0

このインデックスは、私にとっては良いインデックスでした。kristjan – django

関連する問題