我在AdventureWorks2012数据库中运行此查询:
SELECT
s.SalesOrderID,
d.CarrierTrackingNumber,
d.ProductID,
d.OrderQty
FROM Sales.SalesOrderHeader s
JOIN Sales.SalesOrderDetail d
ON s.SalesOrderID = d.SalesOrderID
WHERE s.CustomerID = 11077
Run Code Online (Sandbox Code Playgroud)
如果我查看估计的执行计划,我会看到以下内容:
初始索引查找(右上角)使用 IX_SalesOrderHeader_CustomerID 索引并搜索文字 11077。它估计有 2.6192 行。
如果我使用DBCC SHOW_STATISTICS ('Sales.SalesOrderHeader', 'IX_SalesOrderHeader_CustomerID') WITH HISTOGRAM
,则显示值 11077 介于两个采样键 11019 和 11091 之间。
11019 和 11091 之间不同行的平均数为 2.619718,或四舍五入为 2.61972,这是为索引查找显示的估计行的值。
我不明白的部分是针对 SalesOrderDetail 表的聚集索引查找的估计行数。
如果我运行DBCC SHOW_STATISTICS ('Sales.SalesOrderDetail', 'PK_SalesOrderDetail_SalesOrderID_SalesOrderDetailID')
:
所以 SalesOrderID(我正在加入)的密度是 3.178134E-05。这意味着 1/3.178134E-05 (31465) 等于 SalesOrderDetail 表中唯一 SalesOrderID 值的数量。
如果 SalesOrderDetail 中有 31465 个唯一的 SalesOrderID,那么在均匀分布的情况下,每个 SalesOrderID 的平均行数为 121317(总行数)除以 31465。平均值为 3.85561
因此,如果估计要循环的行数是 …
sql-server optimization execution-plan sql-server-2012 cardinality-estimates query-performance
现在,我面临着基数估计的逻辑问题,这个问题在一个看似相当简单的情况下对我来说不是很清楚。我在工作中遇到过这种情况,因此出于隐私考虑,下面仅对问题进行一般性描述,但为了更详细的分析,我在AdventureWorksDW培训基地中模拟了此问题。
有以下形式的查询:
SELECT <some columns>
FROM <some dates table>
CROSS APPLY(
SELECT
<some p columns>
FROM <some table> p
WHERE p.StartDate <= Dates.d
AND p.EndDate >= Dates.d
) t
Run Code Online (Sandbox Code Playgroud)
从上面给出的执行计划中可以看出,基数估计器估计索引查找操作中的估计行数为 17,884,200(对应于 NL 外部的每行 2,980,700),这与实际数量非常接近.
现在我将修改查询并添加到 CROSS APPLY LEFT OUTER JOIN:
SELECT <some columns t>
FROM <some dates table>
CROSS APPLY(
SELECT
<some p columns>
<some columns f>
FROM <some table> p
LEFT JOIN <some table> f ON p.key = f.key
AND f.date = Dates.d
WHERE p.StartDate <= Dates.d
AND p.EndDate …
Run Code Online (Sandbox Code Playgroud) sql-server optimization cross-apply cardinality-estimates query-performance
AdventureWorks 中的以下简单查询:
SELECT *
FROM Person.Person p
JOIN HumanResources.Employee e
ON p.BusinessEntityID = e.BusinessEntityID
Run Code Online (Sandbox Code Playgroud)
给出以下执行计划:
如果我查看上面的计划,我可以看到索引扫描和索引搜索都(正确)估计了 290 行,但是,连接两者的估计循环运算符估计了 279 行。
旧的估计器也正确地猜测了搜索和扫描中的 290 行,但嵌套循环估计了 289 行,在这个查询的情况下这是一个更好的估计。
那么在新 CE 的情况下,优化器估计当它连接索引扫描中的 290 行和索引查找中的 290 行时,是否会有 11 行不匹配?
它使用什么方法/公式来进行这个估计?
我所说的任何方法都是正确的,它已经从早期的 CE 版本改变了,因为它做出了不同的估计?
我意识到新 CE 的“坏”估计不足以损害性能,我只是想了解估计器处理