我希望有人可以向我解释为什么SQL Server会给我一个与我预期不同的估计。
我的参考链接(http://sqlmag.com/database-development/optimization-tips-multiple-range-predicates-part-1)
表格的25%有string = 'C'
,10%有number = 9
。 25,000实际上有string = 'C' AND number = 9
但是根据指数退避CE,估计的行数应该是50000.但是,我得到25000。
测试脚本
SELECT keycol, string, number
FROM dbo.TStrNum
WHERE string = 'C' AND number = 9
统计
测试服务器:SQL Server 2016
兼容级别:130
示例数据生成脚本
我使用参考链接中提供的相同脚本进行测试。这是
SET NOCOUNT ON;
IF OBJECT_ID(N'dbo.GetNums', N'IF') IS NOT NULL DROP FUNCTION dbo.GetNums;
GO
CREATE FUNCTION dbo.GetNums(@low AS BIGINT, @high AS BIGINT) RETURNS TABLE
AS
RETURN
WITH
L0 AS (SELECT c FROM (SELECT 1 UNION ALL SELECT 1) AS D(c)),
L1 AS (SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
L2 AS (SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
L3 AS (SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
L4 AS (SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
L5 AS (SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
Nums AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS rownum
FROM L5)
SELECT TOP(@high - @low + 1) @low + rownum - 1 AS n
FROM Nums
ORDER BY rownum;
GO
IF OBJECT_ID(N'dbo.TStrNum', N'U') IS NOT NULL DROP TABLE dbo.TStrNum;
CREATE TABLE dbo.TStrNum
(
keycol INT NOT NULL IDENTITY,
string VARCHAR(10) NOT NULL,
number INT NOT NULL
);
INSERT INTO dbo.TStrNum WITH (TABLOCK) (string, number)
SELECT
CHAR(ASCII('A') + S.n) AS string,
N.n AS number
FROM dbo.GetNums(0, 3) AS S
CROSS JOIN dbo.GetNums(1, 10) AS N
CROSS JOIN dbo.GetNums(1, 25000) AS M;
-- Indexes
CREATE UNIQUE CLUSTERED INDEX idx_str_num ON dbo.TStrNum(string, number, keycol);
-- Indexes
-- Trigger creation of histogram on second index key
SELECT keycol, string, number
FROM dbo.TStrNum
WHERE number = 9 AND number % 2 = 0;
-- Update statistics with full scan
UPDATE STATISTICS dbo.TStrNum WITH FULLSCAN;
GO