Query-Performance

排序時的錯誤估計,沒有排序的好估計

  • June 16, 2020

我正在努力調整我們生產 SQL Server 2016 SP2 上的一個查詢。由於安全策略,我需要匿名化查詢。查詢是這樣的:

SELECT TOP 1000 Object1.Column1,Object1.Column2,Object1.Column3,Object1.Column4,Object1.Column5,Object1.Column6,Object1.Column7,Object1.Column8,Object1.Column9,Object1.Column10,Object1.Column11,Object1.Column12,Object1.Column13,Object1.Column14,Object1.Column15,Object1.Column16,Object1.Column17,Object1.Column18,Object1.Column19,Object1.Column20,Object1.Column21,Object1.Column22,Object1.Column23,Object1.Column24,Object1.Column25,Object1.Column26,Object1.Column27,Object1.Column28,Object1.Column29,Object1.Column30,Object1.Column31,Object1.Column32,Object1.Column33,Object1.Column34,Object1.Column35,Object1.Column36,Object1.Column37,Object1.Column38,Object1.Column39,Object1.Column40,Object1.Column41,Object1.Column42,Object1.Column43,Object1.Column44,Object1.Column45,Object1.Column46,Object1.Column47,Object1.Column48,Object1.Column49,Object1.Column50,Object1.Column51,Object1.Column52
FROM Schema1.Object2 Object1
LEFT OUTER JOIN Schema1.Object3 Object4 ON Object4.Column3 = Object1.Column3
WHERE ((Object1.Column43 IS NULL OR Object1.Column43='') AND (Object4.Column54 = 0 OR Object4.Column54 IS NULL) AND Object1.Column3 = N'SomeValue')
ORDER BY Object1.Column3 ASC,Object1.Column8 ASC,Object1.Column7 ASC,Object1.Column12 ASC,Object1.Column13 ASC,Object1.Column1 ASC

可以在此處
找到實際的查詢計劃 正如您所見,在 Object2.Index1.Object1 上完成了索引搜尋,但估計很糟糕。SQL Server 估計將返回 194907 行,但僅返回 710 行。

當我刪除該ORDER BY子句時,估計要好得多,SQL Server 預計只有 1181 行返回。該計劃可以在這裡找到。

我不明白為什麼 anORDER BY會影響索引搜尋的估計。兩個查詢都使用相同的 column3 值執行。

有人可以向我解釋一下嗎?

為什麼 ORDER BY 會影響索引搜尋的估計。有人可以向我解釋一下嗎?

這是一個最高值查詢。ORDER BY 指定查詢將返回1000 行。如果沒有 ORDER BY,SQL Server 可以自由返回任何 1000。因此,一旦 SQL Server 從 Schema1.Object2 中有 1000 行符合 WHERE 子句的條件,它就可以停止。LEFT JOIN 不能減少行數。

具體來說,no-ORDER BY 計劃在讀取 Object2 時有一個行目標:

   <RelOp AvgRowSize="698" EstimateCPU="0.814711" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" 
EstimateRows="1181.27" EstimateRowsWithoutRowGoal="194907" 
LogicalOp="Inner Join" NodeId="3" Parallel="false" PhysicalOp="Nested Loops" EstimatedTotalSubtreeCost="3.89162">

ORDER BY 計劃沒有。在確定要返回的 1000之前,需要對所有過濾的行進行排序。

<RelOp AvgRowSize="51" EstimateCPU="0.214555" EstimateIO="1.3572" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" 
EstimateRows="194907" 
EstimatedRowsRead="194907" LogicalOp="Index Seek" NodeId="17" Parallel="false" PhysicalOp="Index Seek" EstimatedTotalSubtreeCost="1.57175" TableCardinality="42781400">

引用自:https://dba.stackexchange.com/questions/269282