[英]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),有什么辦法可以避免這種情況?
這在很大程度上取決於您的模式和使用模式,但是有一些嘗試。
TRIM
時,數據庫必須在要評估的每一行上運行它,這很浪費。 如果您保證始終對號碼進行修整,則可以進行更簡單的telephone = '06868787878'
檢查。 如果很常見,請確保telephone
上有索引。 telephone
數據,請在表達式 TRIM(telephone)
上創建一個索引 。 這有效地預計算所有的工作TRIM
是干什么的,但顯然僅僅是有幫助的仰視TRIM(telephone) = '123'
,而不是telephone = '123'
自行了。 將索引放在最具體的列上。 例如。 如果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.