【问题标题】:Estimating range predicate with SQL Server statistics histogram使用 SQL Server 统计直方图估计范围谓词
【发布时间】:2017-06-20 10:29:08
【问题描述】:

我想问一下SQL Server如何在下面的查询中估计那些行,如果它使用直方图来计算估计行,它是怎么做的。任何提示或答案的链接都非常感谢。

 use AdventureWorks2012
go
select *
from sales.SalesOrderDetail 
where SalesOrderID between 43792 and 44000
option (recompile)

this is execution plan

this is statistics info

【问题讨论】:

    标签: sql-server database-performance query-performance database-optimization


    【解决方案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 和

    EQ_ROWS:

    指定有多少行恰好等于 1 到最高值。在这种情况下,它是 = 1 ,3 等等

    DISTINCT_RANGE_ROWS:

    这些是一个步骤中的不同行数。如果所有行都是唯一的,那么 RANGE_ROWS 和 DISTINCT_RANGE_ROWS 将相等。

    值 >1 和

    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/

    【讨论】:

    • 感谢您的支持,您的回答并不是我所期望的,但根据您的提示,我可以自己猜出答案。实际上,我的问题还不够清楚,真正的问题是当谓词介于两个步骤(两个 RANGE_HI_KEY 值)之间时,我们如何计算估计的行数?查询看起来像 select * from sales.SalesOrderDetail where SalesOrderID
    • 如果我们无法确切知道 SQL Server 使用了哪个公式?
    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多