Performance
減少此 COUNT() 查詢的持續時間
我有一張有 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_fk
是bigint
並且具有外鍵索引(非聚集)- 該列
mcon_data
是datetime
並且具有索引(非聚集)- 該表具有自增 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
如果問題僅針對涉及此表的查詢,則使用腳本)。