簡體   English   中英

單計數查詢花費太多時間PostgreSQL

[英]Single count query taking too much time postgresql

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),有什么辦法可以避免這種情況?

這在很大程度上取決於您的模式和使用模式,但是有一些嘗試。

  1. 在將電話號碼輸入數據庫時​​(而不是在進行此計數時)修剪電話號碼。 在計數期間使用TRIM時,數據庫必須在要評估的每一行上運行它,這很浪費。 如果您保證始終對號碼進行修整,則可以進行更簡單的telephone = '06868787878'檢查。 如果很常見,請確保telephone上有索引。
  2. 如果您不能或不想在查詢前修剪telephone數據,請在表達式 TRIM(telephone) 上創建一個索引 這有效地預計算所有的工作TRIM是干什么的,但顯然僅僅是有幫助的仰視TRIM(telephone) = '123' ,而不是telephone = '123'自行了。
  3. 將索引放在最具體的列上。 例如。 如果check_id在2行中只有41個,則Postgres可以首先使用該索引來縮小集合的范圍,然后驗證其余條件的工作量很小。 如果check_id往往是41 ,但telephone是只是偶爾06868787878 ,同樣適用,你應該有你的指數telephone 如果兩者都相當均勻地分布並且這是一種常見的查詢模式,則可能需要在(check_id, telephone)上使用多列索引 遵循與單列索引相同的推理,將更具體的列放在第一位,或者,如果您還需要僅對其中一列進行過濾,則將該列放在第一位。 例如。 (check_id, telephone)索引也使您可以有效地查詢check_id前綴。

    3b。 創建一個涵蓋您所有條件的多列索引可能會非常有效,因為Postgres可以僅使用索引來執行計數,而無需執行輔助查找來獲取主記錄並檢查該索引未涵蓋的條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM