Performance

減少此 COUNT() 查詢的持續時間

  • May 13, 2020

我有一張有 2,161,524 行的表。我認為計數查詢花費的時間太長。

select count(mcon_codigo_pk) from tbMovimentoConta
-- count = 2,161,524
-- time = 9 seconds

select count(1) from tbMovimentoConta 
where con_codigo_fk = 1 
and mcon_data between '2015-01-05' and '2016-01-06'
-- count = 1,034,729 
-- time = 13 seconds

細節:

  • 該列con_codigo_fkbigint並且具有外鍵索引(非聚集)
  • 該列mcon_datadatetime並且具有索引(非聚集)
  • 該表具有自增 PK(聚集索引)
  • 還有另外三個具有索引的外部(所有索引都是由實體框架創建的)

索引創建腳本

CREATE NONCLUSTERED INDEX [ix_mcon_data] ON [dbo].[tbMovimentoConta]
(
   [mcon_data] ASC
)
WITH (
   PAD_INDEX = OFF
   , STATISTICS_NORECOMPUTE = OFF
   , SORT_IN_TEMPDB = OFF
   , DROP_EXISTING = OFF
   , ONLINE = OFF
   , ALLOW_ROW_LOCKS = ON
   , ALLOW_PAGE_LOCKS = ON
);
GO

在此處輸入圖像描述

我的電腦有 8GB RAM 和執行 Windows 10 的 Core i7。

我的查詢真的需要很長時間還是平均預期時間?如果它們需要很長時間,我該怎麼做才能使它們更快?

查詢的覆蓋索引有兩種可能性:

  • 上的綜合指數(con_codigo_fk, mcon_data)。這將涵蓋所有類似的查詢。如果您添加此索引,您可以(很可能)安全地刪除該索引,(con_codigo_fk)並使用新的索引。另一個索引(mcon_data)可以被不同的查詢使用,所以我不會刪除它。

添加索引的程式碼:

CREATE INDEX ix__con_codigo_fk__mcon_data       -- choose a name
 ON dbo.tbMovimentoConta
 (con_codigo_fk, mcon_data) ;
  • 上的過濾索引(mcon_data) WHERE (con_codigo_fk = 1)。這當然只對具有特定值 ( 1) 的查詢有用。

此類索引的案例要少得多,因此它可能對您沒有用處。

另一個問題是您使用BETWEEN的是日期時間類型。這會給您帶來不准確的結果,因為它將包含具有確切日期時間的結果'2016-01-06' 00:00:00'

最好使用包含獨占範圍:

select count(*) 
from tbMovimentoConta 
where con_codigo_fk = 1 
 and mcon_data >= '2015-01-05' 
 and mcon_data  < '2016-01-06' ;

@Aaron Bertrand在部落格上對此進行了更詳細的解釋:和魔鬼有****什麼共同點?BETWEEN


另一個問題 - 索引沒有試圖解決 - 是雖然查詢與WHERE條件所需的時間可能是由錯誤的計劃和缺乏適當的索引來解釋的,但第一次查詢的時間,整個表計數( 9秒)聽起來有點太多了。(並且添加索引後查詢的 1 秒也很高)。

我會在沒有更多細節的情況下進行推測,因為解釋可能來自許多不同的原因(一般/記憶體 SQL Server 設置、伺服器上的高負載、廣泛的聚集索引等),所以我建議您添加有關該問題的更多詳細資訊或發布新問題(CREATE TABLE如果問題僅針對涉及此表的查詢,則使用腳本)。

引用自:https://dba.stackexchange.com/questions/160098