我想问一下SQL Server如何估计以下查询中的这些行,如果它使用直方图来计算估计行,它是如何做到的。 任何提示或答案链接都非常感谢。
use AdventureWorks2012
go
select *
from sales.SalesOrderDetail
where SalesOrderID between 43792 and 44000
option (recompile)
这是执行计划
这是统计信息
SQLSERVER 构造列的统计信息以分析该列中的数据分布,并根据该直方图得出估计值
让我们举一个小例子来更多地理解数据。
drop table t1
create table t1
(
id int
)
insert into t1
select top 300 row_number() over(order by t1.number) as N
from master..spt_values t1
cross join master..spt_values t2
go 3
select * from t1 where id=1
dbcc show_statistics('t1','_WA_Sys_00000001_29572725')
DBCC 在直方图下面给了我
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
1 0 3 0 1
3 3 3 1 3
4 0 3 0 1
6 3 3 1 3
8 3 3 1 3
10 3 3 1 3
以上是 dbcc 输出的片段。在开始解释这些含义之前。让我们了解数据在表中的分布方式
从1到300有300行,重复3次。所以总行数是 900
现在让我们了解这些列的含义
RANGE_HI_KEY:
SQL Server使用此列中的值作为构造直方图的顶部键,因为直方图仅限于200步。它选择 用于构造直方图的行..这将限制为 200 steps.in 在这种情况下,值为 1,3,4,6 等
RANGE_ROWS:
此数字显示步骤中大于上一个顶键和当前顶键的行数,但不等于两者。
第>1 行和第 <3 行,依此类推
EQ_ROWS :
指定有多少行正好等于 e1 到最大值,在这种情况下,它是 = 1 ,3 依此类推
DISTINCT_RANGE_ROWS :
这些是步骤中不同的行数。如果所有行都是唯一的,则RANGE_ROWS和DISTINCT_RANGE_ROWS将相等。
值为>1 和 <3 等的不同行
AVG_RANGE_ROWS:
这表示步骤中等于键值的平均行数,这意味着平均行数等于顶部键,即 1,3 等
**一些演示查询**
select * from id=1
我们知道 1 的 EQ_rows 的值为 3,因此您可以看到估计的行数为 3
这是简单的相等查询,但它如何适用于多个谓词,例如您的情况。
巴特·邓肯提供了一些见解
优化器有许多方法来估计基数,但没有一种方法是完全万无一失的。
如果谓词很简单,如"column=123",并且搜索值恰好是直方图端点 (RANGE_HI_KEY),则EQ_ROWS可用于非常准确的估计。
如果搜索值恰好落在两个步骤端点之间,则使用该特定直方图步骤中值的平均密度来估计谓词选择性和运算符基数。
如果在编译时不知道特定的搜索值,则下一个最佳选项是使用平均列密度("所有密度"),它可用于计算与列中的平均值匹配的行数。
在某些情况下,以上都是不可能的,优化器必须求助于基于"幻数"的估计。 例如,它可能会完全盲目猜测将返回 10% 的行,其中"10%"值将在优化程序的代码中硬编码,而不是从统计信息派生。
更多参考和阅读:
https://sqlperformance.com/2014/01/sql-plan/cardinality-estimation-for-multiple-predicateshttps://blogs.msdn.microsoft.com/bartd/2011/01/25/query-tuning-fundamentals-density-predicates-selectivity-and-cardinality/