簡體   English   中英

SQL 50 萬條記錄的查詢性能優化

[英]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

關於如何使查詢結構更好的任何建議? 我相信這個結構很差。

更新


  • 另外,我不能使用大量索引,因為表每秒都有大量的更新/插入/刪除事務,並且索引過多會影響 SLA。

您可以在此處進行許多改進,其中最大的改進之一是替換每塊 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”中有索引”。

可以進行兩項重大修改以加快查詢速度。

  1. 正如 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;
  1. 創建索引:

    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.

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