Dha*_*ghe 5 sql-server like cardinality-estimates sql-server-2017
我在名为 AspNetUsers 的表的 LastName 列上创建了非聚集索引的统计直方图向量。
如果我运行查询,因为SELECT * FROM dbo.AspNetUsers WHERE LastName = 'Baker'
它返回 6 行作为估计行,因为Baker是步骤之一的RANGE_HI_KEY ,因此 EQ_ROWS 值是我的估计行数。同样,如果我运行查询SELECT * FROM dbo.AspNetUsers WHERE LastName = 'Bacilia'
,它会返回 1 行作为估计行,导致Bacilia落入“Baker”步长范围,因此该步长的AVG_RAGE_ROWS值是我的估计行数。
同样,根据我的理解,如果我执行查询,因为SELECT * FROM dbo.AspNetUsers WHERE LastName LIKE 'Ba%'
它匹配 2 个步骤(Baker和Batagoda),所以它应该返回 27 + 51 (RANGE_ROWS) + 6 + 4 (EQ_ROWS) = 88。但它返回 99 行作为估计。
此基数估计如何与 LIKE 查询一起使用?在执行 LIKE 查询时,它是否使用不同的公式来估计行数?
在执行 LIKE 查询时,它是否使用不同的公式来估计行数?
是的。
我不太了解血淋淋的细节,但请参阅此处提到的“字符串摘要统计”
统计对象包含字符串摘要统计信息,以改进使用 LIKE 运算符的查询谓词的基数估计;例如,WHERE ProductName LIKE '%Bike'。字符串摘要统计信息与直方图分开存储,并且当统计对象的类型为 char、varchar、nchar、nvarchar、varchar(max)、nvarchar(max)、text 或 ntext 时,在统计对象的第一个键列上创建。
我没有您的样本数据,但只是尝试了一下player_overviews_unindexed网球运动员数据集。
直方图的相关部分是
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
----------------------------------------------------------------------------------
Aubone 40 4 37 1.081081
Baker 79 12 60 1.316667
Barker 71 6 55 1.290909
Barton 46 4 25 1.84
Bates 26 5 20 1.3
Becker 45 6 35 1.285714
Run Code Online (Sandbox Code Playgroud)
统计数据仅明确显示该范围将包含至少 170 行 (12 + 71 + 6 + 46 + 4 + 26 + 5)。当考虑到结束范围时最多为 294。
当我对last_name
列建立索引时last_name LIKE N'Ba%'
,谓词被转换为索引查找last_name >= N'Ba' AND last_name < N'BB'
和剩余谓词,但估计值不同。
last_name >= N'Ba' AND last_name < N'BB'
180.525 行。last_name LIKE N'Ba%'
235.935 行LEFT(last_name, 2) = 'Ba'
171.317 行。因为它可能只是将 的值LEFT
添加到最小值 170 上。AVG_RANGE_ROWS
1.316667
当进行简单的索引范围查找时,它看起来只是查看结束直方图步骤的范围大小以及查询将选择的范围,并基于此进行一些插值。
last_name > 'Aubone' and last_name < 'Baker'
所以直方图中有 79 行( RANGE_ROWS
)。
它估计77.6735
这 79 行中的行将在该范围内< 'Ba'
,并且只有 1.3265 行在该范围内>= 'Ba'
- 尽管实际上数字分别是34
和45
。
有很多姓氏的球员(Babcock、Bahrami、Baer、Backe、Baghdatis、7 * Baileys 等)都属于该范围,但它无法从直方图中知道这一点。
据推测,字符串摘要统计数据确实比仅从直方图中更好地捕获了分布。