簡體   English   中英

為什么選擇前X個性能下降

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

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