[英]Why Does Select Top X Kill Performance
我下面有T-SQL查詢(由linq-to-sql生成,因此看起來有點怪異。)當我刪除前10個查詢時,它的運行時間不到1秒。 當我留在前十名時,需要68秒。
沒有前10名,行的總數僅為19。
在這種情況下,為什么前10名會嚴重破壞性能?
SELECT TOP (10) [t3].[value] AS [StartDate], [t3].[AH_TimeStamp4] AS [EndDate], [t3].[value2] AS [RunTime], [t3].[AH_Idnr] AS [RunNumber], [t3].[AH_Status] AS [StatusCode], [t3].[STATUS_DESC] AS [StatusDesc], [t3].[STATUS_TYPE] AS [StatusType]
FROM (
SELECT COALESCE([t1].[AH_TimeStamp2],[t1].[AH_TimeStamp1]) AS [value], [t1].[AH_TimeStamp4], CONVERT(BigInt,(((CONVERT(BigInt,DATEDIFF(DAY, [t1].[AH_TimeStamp1], [t1].[AH_TimeStamp4]))) * 86400000) + DATEDIFF(MILLISECOND, DATEADD(DAY, DATEDIFF(DAY, [t1].[AH_TimeStamp1], [t1].[AH_TimeStamp4]), [t1].[AH_TimeStamp1]), [t1].[AH_TimeStamp4])) * 10000) AS [value2], [t1].[AH_Idnr], [t1].[AH_Status], [t2].[STATUS_DESC], [t2].[STATUS_TYPE], [t0].[OH_Name]
FROM [dbo].[OH] AS [t0]
INNER JOIN [dbo].[AH] AS [t1] ON ([t0].[OH_Idnr]) = [t1].[AH_OH_Idnr]
INNER JOIN [dbo].[CHK_JOB_STATUS_CODE] AS [t2] ON [t1].[AH_Status] = ([t2].[STATUS_CODE])
) AS [t3]
WHERE [t3].[OH_Name] = @p0
ORDER BY [t3].[AH_Idnr] DESC
編輯->根據要求,這是不帶Take(10)的linq生成的查詢
SELECT [t3].[value] AS [StartDate], [t3].[AH_TimeStamp4] AS [EndDate], [t3].[value2] AS [RunTime], [t3].[AH_Idnr] AS [RunNumber], [t3].[AH_Status] AS [StatusCode], [t3].[STATUS_DESC] AS [StatusDesc], [t3].[STATUS_TYPE] AS [StatusType]
FROM (
SELECT COALESCE([t1].[AH_TimeStamp2],[t1].[AH_TimeStamp1]) AS [value], [t1].[AH_TimeStamp4], CONVERT(BigInt,(((CONVERT(BigInt,DATEDIFF(DAY, [t1].[AH_TimeStamp1], [t1].[AH_TimeStamp4]))) * 86400000) + DATEDIFF(MILLISECOND, DATEADD(DAY, DATEDIFF(DAY, [t1].[AH_TimeStamp1], [t1].[AH_TimeStamp4]), [t1].[AH_TimeStamp1]), [t1].[AH_TimeStamp4])) * 10000) AS [value2], [t1].[AH_Idnr], [t1].[AH_Status], [t2].[STATUS_DESC], [t2].[STATUS_TYPE], [t0].[OH_Name]
FROM [dbo].[OH] AS [t0]
INNER JOIN [dbo].[AH] AS [t1] ON ([t0].[OH_Idnr]) = [t1].[AH_OH_Idnr]
INNER JOIN [dbo].[CHK_JOB_STATUS_CODE] AS [t2] ON [t1].[AH_Status] = ([t2].[STATUS_CODE])
) AS [t3]
WHERE [t3].[OH_Name] = @p0
ORDER BY [t3].[AH_Idnr] DESC
編輯2->這是LINQ查詢-沒什么特別的,只有3個聯接
List<UC4Status> statusList = uc4DB.OHs.Where(o => o.OH_Name == jobName).Join(uc4DB.AHs, oh => oh.OH_Idnr, ah => ah.AH_OH_Idnr, (oh, ah) => ah)
.Join(uc4DB.CHK_JOB_STATUS_CODEs, ah => ah.AH_Status, job => job.STATUS_CODE, (a, s) =>
new UC4Status
{
StartDate = a.AH_TimeStamp2 ?? a.AH_TimeStamp1,
EndDate = a.AH_TimeStamp4,
RunTime = a.AH_TimeStamp4 - a.AH_TimeStamp1,
StatusType = s.STATUS_TYPE,
StatusDesc = s.STATUS_DESC,
StatusCode = a.AH_Status,
RunNumber = a.AH_Idnr
}).OrderByDescending(r => r.RunNumber).Take(maxResults).ToList();
比返回的行數更重要的是每個連接的表中的行數。 如果無法訪問查詢計划,很難說出問題所在。 但是,此問題很可能是由於列統計信息過時或丟失以及缺少良好索引所致,導致在使用top
時查詢優化器做出了非常糟糕的決定。 例如,如果優化器錯誤地假設top
語句僅對每個聯接表中的少量行進行操作,則它可以選擇對每個聯接表使用內部循環聯接和表掃描,這可能是非常糟糕的。對大量記錄的操作速度較慢(但是在僅處理少數記錄時可以非常有效地工作)。 在沒有top
的情況下,優化器可以正確地假定它將必須掃描聯接表中的大量記錄,並使用一種更適合此類操作的方法,例如從表掃描進行哈希匹配聯接。
您可以嘗試更新統計信息並添加其他索引以查看是否有幫助。
沒有前10名的行數是多少? 是否實現了任何索引? 我猜這是由於t0,t1和t2的子查詢聯接導致的。
select top 10 * from ( select t3.value.... from ( select coalesce... ) where ... order by ... )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.