我想问一下SQL Server如何在下面的查询中估计这些行,如果它使用直方图来计算估计行,它是如何做的。任何有关答案的提示或链接都非常感激。
use AdventureWorks2012
go
select *
from sales.SalesOrderDetail
where SalesOrderID between 43792 and 44000
option (recompile)
答案 0 :(得分:1)
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步。在这种情况下,值为1,3,4,6等等
RANGE_ROWS :
此数字显示步骤中的行数大于上一个顶部键和当前顶部键,但不等于任何一个。
行> 1和< 3等等
EQ_ROWS:
指定有多少行正好等于顶值。在这种情况下,它是= 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
这是为了简单的查询,但它如何适用于多个谓词,例如你的情况。
Bart Duncan提供了一些见解
优化器有多种方法可以估算基数,但没有一种方法可以完全万无一失。
如果谓词很简单,如“column = 123”,并且搜索值恰好是直方图端点(RANGE_HI_KEY),则EQ_ROWS可用于非常准确的估计。
如果搜索值恰好落在两个步骤端点之间,则使用该特定直方图步骤中的平均值密度来估计谓词选择性和运算符基数。
如果在编译时未知特定搜索值,则下一个最佳选项是使用平均列密度(“所有密度”),该密度可用于计算与平均值相匹配的行数。柱。
在某些情况下,上述情况都不可能,优化程序必须采用基于“幻数”的估算。例如,它可能会完全盲目地猜测将返回10%的行,其中“10%”值将在优化程序的代码中进行硬编码,而不是从统计数据派生。
进一步参考和阅读:
https://sqlperformance.com/2014/01/sql-plan/cardinality-estimation-for-multiple-predicates
https://blogs.msdn.microsoft.com/bartd/2011/01/25/query-tuning-fundamentals-density-predicates-selectivity-and-cardinality/