[英]SQL Query Performance Optimization on half million records
我正在使用具有五個表的數據庫,並且我創建了一個 SP 來概述所有五個表。 所有 5 個表的總和沒有達到 50 萬條記錄,但 SP 需要 20 - 50 秒才能給我計數。 我已經創建了索引,但仍然沒有運氣。
下面是我的SP:
ALTER procedure [dbo].[sp_TableCounts]
@TotalRecords int output,
@TodayRecords int output,
@New int output,
@Modified int output,
@Deleted int output,
@DeletedToday int output,
@TotalError int output,
@Table1NewRecords int output,
@Table1ModifiedRecords int output,
@Table1DeletedRecords int output,
@Table1ErrorRecords int output,
@Table2NewRecords int output,
@Table2ModifiedRecords int output,
@Table2DeletedRecords int output,
@Table2ErrorRecords int output,
@Table3NewRecords int output,
@Table3ModifiedRecords int output,
@Table3DeletedRecords int output,
@Table3ErrorRecords int output,
@Table4NewRecords int output,
@Table4ModifiedRecords int output,
@Table4DeletedRecords int output,
@Table4ErrorRecords int output,
@Table5NewRecords int output,
@Table5ModifiedRecords int output,
@Table5DeletedRecords int output,
@Table5ErrorRecords int output
as
begin
SELECT @TotalRecords =
(select count(1) from Table1)
+
(select count(1) from Table2)
+
(select count(1) from Table3)
+
(select count(1) from Table4)
+
(select count(1) from Table5)
SELECT @TodayRecords =
(select count(1) from Table1 where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table2 where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table3 where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table4 where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table5 where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
SELECT @New =
(select count(1) from Table1 where RecordStatus = 1)
+
(select count(1) from Table2 where RecordStatus = 1)
+
(select count(1) from Table3 where RecordStatus = 1)
+
(select count(1) from Table4 where RecordStatus = 1)
+
(select count(1) from Table5 where RecordStatus = 1)
SELECT @Modified =
(select count(1) from Table1 where RecordStatus = 2)
+
(select count(1) from Table2 where RecordStatus = 2)
+
(select count(1) from Table3 where RecordStatus = 2)
+
(select count(1) from Table4 where RecordStatus = 2)
+
(select count(1) from Table5 where RecordStatus = 2)
SELECT @Deleted =
(select count(1) from Table1 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')))
+
(select count(1) from Table2 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')))
+
(select count(1) from Table3 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')))
+
(select count(1) from Table4 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')))
+
(select count(1) from Table5 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')))
SELECT @DeletedToday =
(select count(1) from Table1 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')) and Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table2 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')) and Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table3 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')) and Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table4 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')) and Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
+
(select count(1) from Table5 where (RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B')) and Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103))
SELECT @TotalError =
(select count(1) from Table1 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
+
(select count(1) from Table2 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
+
(select count(1) from Table3 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
+
(select count(1) from Table4 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
+
(select count(1) from Table5 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
SELECT @Table1NewRecords = (select count(1) from Table1 where RecordStatus = 1)
SELECT @Table1ModifiedRecords = (select count(1) from Table1 where RecordStatus = 2)
SELECT @Table1DeletedRecords = (select count(1) from Table1 where RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B'))
SELECT @Table1ErrorRecords = (select count(1) from Table1 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
SELECT @Table2NewRecords = (select count(1) from Table2 where RecordStatus = 1)
SELECT @Table2ModifiedRecords = (select count(1) from Table2 where RecordStatus = 2)
SELECT @Table2DeletedRecords = (select count(1) from Table2 where RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B'))
SELECT @Table2ErrorRecords = (select count(1) from Table2 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
SELECT @Table3NewRecords = (select count(1) from Table3 where RecordStatus = 1)
SELECT @Table3ModifiedRecords = (select count(1) from Table3 where RecordStatus = 2)
SELECT @Table3DeletedRecords = (select count(1) from Table3 where RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B'))
SELECT @Table3ErrorRecords = (select count(1) from Table3 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
SELECT @Table4NewRecords = (select count(1) from Table4 where RecordStatus = 1)
SELECT @Table4ModifiedRecords = (select count(1) from Table4 where RecordStatus = 2)
SELECT @Table4DeletedRecords = (select count(1) from Table4 where RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B'))
SELECT @Table4ErrorRecords = (select count(1) from Table4 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
SELECT @Table5NewRecords = (select count(1) from Table5 where RecordStatus = 1)
SELECT @Table5ModifiedRecords = (select count(1) from Table5 where RecordStatus = 2)
SELECT @Table5DeletedRecords = (select count(1) from Table5 where RecordStatus = 3 or ([Status] = 'A') or ([Status] = 'B'))
SELECT @Table5ErrorRecords = (select count(1) from Table5 where RecordStatus = 4 and ([Status] != 'A') and ([Status] != 'B'))
end
關於如何使查詢結構更好的任何建議? 我相信這個結構很差。
更新
您可以在此處進行許多改進,其中最大的改進之一是替換每塊 5 個重復選擇,如下所示:
select
@Table1NewRecords=Sum (case when recordstatus=1 then 1 else 0 end)
@Table1ModifiedRecords=Sum (case when recordstatus=2 then 1 else 0 end)
@Table1DeletedRecords=Sum (case when recordstatus=3 or [Status] in( 'A','B') then 1 else 0 end)
@Table1ErrorRecords=Sum (case when recordstatus=4 and [Status] != 'A' and [Status] != 'B' then 1 else 0 end)
from table1
where recordstatus between 1 and 4
和上面一樣,如果您重復掃描相同的表以獲得不同的計數,您只能點擊表一次並使用條件總和來計算相關行。
您還應該考慮在 RecTimestamp 上添加 function 作為永久列,並在其上建立索引,因為where Convert(date,CONVERT(datetime,RecTimestamp,120),103)
是不可搜索的,並且將強制掃描每個表。 這是因為 SQL 首先必須對每一行執行計算才能知道它是否合格。
此外,由於您使用的是batchmode
2017,因此批處理模式可以提高這些類型查詢的性能,您需要查看執行計划並檢查各種運算符的執行模式。
由於對 where 子句謂詞中的過濾器列進行的數據類型轉換,即使這些索引存在,其中一些查詢也無法使用索引。
例如, “where Convert(date,CONVERT(datetime,RecTimestamp,120),103) = Convert(date,GETDATE(),103)) 之類的內容將導致全表掃描,即使“RecTimestamp”中有索引”。
可以進行兩項重大修改以加快查詢速度。
正如 KrsitoferA 所說,替換
轉換(日期,轉換(日期時間,RecTimestamp,120),103)=轉換(日期,GETDATE(),103))
...經過:
WHERE RecTimestamp >= CAST(GETDATE() AS DATE)
AND RecTimestamp < CAST(DATEADD(day, 1, GETDATE()) AS DATE)
這將通過 sargable 並使用索引。
其次,在 table1..5 中添加一些持久計算列:
ALTER TABLE Table1
ADD STATUS_4_AND_A_OR_B
AS CAST(CASE WHEN RecordStatus = 3 or [Status] = 'A' or [Status] = 'B' THEN 1 ELSE 0 END AS BIT) PERSISTED;
ALTER TABLE Table1
ADD STATUS_4_NOT_A_NOT_B
AS CAST(CASE WHEN RecordStatus = 4 and [Status] <> 'A' and [Status] <> 'B' THEN 1 ELSE O END AS BIT) PERSISTED;
創建索引:
X1: (RecordStatus) X2: (STATUS_4_AND_A_OR_B) X3: (STATUS_4_AND_A_OR_B, RecTimestamp) X4: (STATUS_4_NOT_A_NOT_B)
享受
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.