指数寻求运营商成本


9

对于下面的AdventureWorks示例数据库查询:

SELECT 
    P.ProductID, 
    CA.TransactionID
FROM Production.Product AS P
CROSS APPLY
(
    SELECT TOP (1)
        TH.TransactionID
    FROM Production.TransactionHistory AS TH
    WHERE
        TH.ProductID = P.ProductID
    ORDER BY 
        TH.TransactionID DESC
) AS CA;

执行计划显示针对Index Seek估计运营商成本0.0850383(93%):

计划

成本与使用的基数估计模型无关。

这不是“ 估计的CPU成本”和“ 估计的I / O成本”的简单相加。一次执行索引搜索的成本也不乘以估计的执行次数

这个费用数字是如何得出的?

Answers:


10

完整的成本推导逻辑很复杂,但是对于问题中相对简单的情况:

输入项

  1. 操作员被执行的次数
    这是估计的执行次数504

  2. 索引中的基数(总行数)Index Seek运算符
    TableCardinality属性给出:113,443

  3. 索引中的数据页数:201
    此数字可以通过多种方式获得,例如sys.allocation_units

    SELECT 
        AU.data_pages
    FROM sys.allocation_units AS AU
    JOIN sys.partitions AS P
        ON P.hobt_id = AU.container_id
    WHERE
        AU.[type_desc] = N'IN_ROW_DATA'
        AND P.[object_id] = OBJECT_ID(N'Production.TransactionHistory', N'U')
        AND P.index_id = 
            INDEXPROPERTY(P.[object_id], N'IX_TransactionHistory_ProductID', 'IndexID');
  4. 索引的密度(1 / 离散):0.002267574
    在索引统计的密度向量中可用:

    DBCC SHOW_STATISTICS 
    (
        N'Production.TransactionHistory', 
        N'IX_TransactionHistory_ProductID'
    ) 
    WITH DENSITY_VECTOR;

    密度

计算方式

-- Input numbers
DECLARE
    @Executions float = 504,
    @Density float = 0.002267574,
    @IndexDataPages float = 201,
    @Cardinality float = 113443;

-- SQL Server cost model constants
DECLARE
    @SeqIO float = 0.000740740740741,
    @RandomIO float = 0.003125,
    @CPUbase float = 0.000157,
    @CPUrow float = 0.0000011;

-- Computation
DECLARE
    @IndexPages float = CEILING(@IndexDataPages * @Density),
    @Rows float = @Cardinality * @Density,
    @Rebinds float = @Executions - 1e0;

DECLARE
    @CPU float = @CPUbase + (@Rows * @CPUrow),
    @IO float = @RandomIO + (@SeqIO * (@IndexPages - 1e0)),
    -- sample with replacement
    @PSWR float = @IndexDataPages * (1e0 - POWER(1e0 - (1e0 / @IndexDataPages), @Rebinds));

-- Cost components (no rewinds)
DECLARE
    @InitialCost float = @RandomIO + @CPUbase + @CPUrow,
    @RebindCPU float = @Rebinds * (1e0 * @CPUbase + @CPUrow),
    @RebindIO float = (1e0 / @Rows) * ((@PSWR - 1e0) * @IO);

-- Result
SELECT 
    OpCost = @InitialCost + @RebindCPU + @RebindIO;

db <>小提琴

结果


伟大的工作,很高兴知道估算的成本来自何处,哪些变量会影响估算的成本和比例。这是所有SQL Server版本的机制吗?常量中可能有一些变化?
EzLo

2
据我所知,这方面的成本计算自2005年以来没有改变。
保罗怀特9
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.