我在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
我试图了解 SQL Server 如何估计下面的 Stack Overflow 数据库查询的基数
首先,我创建索引
CREATE INDEX IX_PostId ON dbo.Comments
(
PostId
)
INCLUDE
(
[Text]
)
Run Code Online (Sandbox Code Playgroud)
这是查询:
SELECT u.DisplayName,
c.PostId,
c.Text
FROM Users u
JOIN Comments c
ON u.Reputation = c.PostId
WHERE u.AccountId = 22547
Run Code Online (Sandbox Code Playgroud)
执行计划在这里
首先,SQL Server 扫描用户表上的聚集索引以返回与 AccountId 谓词匹配的用户。我可以看到它使用了这个统计数据:_WA_Sys_0000000E_09DE7BCC
我可以看到该用户没有范围高键,因此 SQL Server 使用 avg_range 行并估计 1
评论索引搜索的搜索谓词是
soScalar Operator([StackOverflow2010].[dbo].[Users].[Reputation] as [u].[Reputation]表示users表中accountId为的用户的信誉值22547
我可以看到总共加载了三个统计数据:
_WA_Sys_0000000E_09DE7BCC- Users.AccountId(用于估计聚集索引查找谓词)
IX_PostId- Comments.PostId(用于估计索引查找谓词)
_WA_Sys_0000000A_09DE7BCC- 用户.声誉 (?)
SQL Server 如何得出索引查找的估计值?它无法在编译时知道 accountId 的信誉,22547因为帐户 …
sql-server execution-plan cardinality-estimates sql-server-2019