更新统计信息:索引扫描的估计行数不等于实际。为什么?

k29*_*k29 4 sql-server statistics execution-plan sql-server-2017

我试图了解强制使用全扫描更新统计信息对执行计划估计的影响。

我目前在一个非常简单的 SELECT 查询的执行计划中有以下结果: 在此处输入图片说明

如您所见,它相差 5 行。

然后我运行:

UPDATE STATISTICS  Person.Address WITH FULLSCAN
UPDATE STATISTICS  Person.Address [PK_Address_AddressID] WITH FULLSCAN
GO
EXEC sp_recompile 'Person.Address';
GO
SELECT * FROM Person.Address OPTION(RECOMPILE)
Run Code Online (Sandbox Code Playgroud)

但是,它仍然相差 5 行。为什么?

我知道除非有性能问题,否则我不应该担心。但是,我试图了解完整统计信息更新的实际效果

For*_*est 8

行数似乎只包含 6 个有效数字的信息(显然称为浮点数的尾数)。

考虑下面的示例,它有一个包含 11,111,111 行的表。但是,估计行仅显示为 11,111,100。

USE TestDB
GO

DROP TABLE IF EXISTS dbo.stattest
GO
CREATE TABLE dbo.stattest (ID int primary key, junk char(1))

INSERT dbo.stattest
SELECT TOP 11111111 ROW_NUMBER() OVER(ORDER BY 1/0), 'a'
FROM master..spt_values a
CROSS JOIN master..spt_values b
CROSS JOIN master..spt_values c

SELECT COUNT(*)
FROM dbo.stattest
Run Code Online (Sandbox Code Playgroud)

有趣的是,stats 对象显示了所有 11,111,111 行。

UPDATE STATISTICS dbo.stattest WITH FULLSCAN
GO
SELECT *
FROM sys.dm_db_stats_properties(OBJECT_ID('dbo.stattest'),1)
Run Code Online (Sandbox Code Playgroud)

通过添加TF 2363,可以看到在基数估计过程中发生了舍入。

SELECT COUNT(*)
FROM dbo.stattest
OPTION(
QUERYTRACEON 3604,
QUERYTRACEON 2363
)
Run Code Online (Sandbox Code Playgroud)

CStCollBaseTable(ID=1, CARD=1.11111e+007 TBL: dbo.stattest)