相关疑难解决方法(0)

SQL Server 的优化器如何估计联接表中的行数?

我在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

13
推荐指数
1
解决办法
2734
查看次数

在 SQL Server 中应用基数估计问题

现在,我面临着基数估计的逻辑问题,这个问题在一个看似相当简单的情况下对我来说不是很清楚。我在工作中遇到过这种情况,因此出于隐私考虑,下面仅对问题进行一般性描述,但为了更详细的分析,我在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

10
推荐指数
1
解决办法
390
查看次数

嵌套循环运算符使用什么方法/公式进行行估计?

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 的“坏”估计不足以损害性能,我只是想了解估计器处理

sql-server sql-server-2016 cardinality-estimates

3
推荐指数
1
解决办法
136
查看次数