【发布时间】:2021-12-24 19:24:41
【问题描述】:
我有大表和具有 3 个 int 字段的聚集索引的简单情况。当我使用前 2 个过滤时,估计的行数不正确,因为统计数据显示错误的数字。这是在 SQL Server 2019 CU12 上测试的。所有 SQL Server 版本都存在同样的问题。我测试的最低版本是带有所有服务包的 SQL 2008。
这是我的 SQL 代码(示例)
create table dbo.glp_test (NagId bigint not null, Lp bigint not null,Id bigint not null, opis varchar(200), CONSTRAINT BK_glp_test PRIMARY KEY CLUSTERED(NagId, Lp, id))
GO
create function dbo.genNum(@start int, @end int)
returns @t table (num int not null identity(1,1))
begin
while @start<=@end
begin
insert into @t default values
set @start = @start+1;
end
return;
end
GO
insert into dbo.glp_test (NagId, lp, Id, opis)
select s.Num, c.Num, c.Num*c2.Num, convert(varchar(100), c.Num*c2.Num)
from dbo.genNum(1,10000) s
cross apply dbo.genNum(1,30) c
cross apply dbo.genNum(1,30) c2
GO
update statistics glp_test with fullscan
GO
dbcc show_statistics('glp_test','BK_glp_test')
GO
-- select [rows]*[All density]
select 9000000*3.333333E-06 -- 29,999997 - correct
GO
update statistics glp_test
GO
dbcc show_statistics('glp_test','BK_glp_test')
GO
-- select [rows]*[All density]
select 9000000*8.609557E-05 -- 774,86013 - dramatically incorrect
GO
现在,如果我使用字段 1 和字段 2 的确切值查询表 glp_test,则估计的行数是错误的。估计应该接近 30。使用全扫描更新统计信息可以解决问题,但这不是解决方案。如何解决这个问题?
declare @Nagid bigint, @Lp bigint
select * from dbo.glp_test where NagID = @NagId and Lp = @Lp
【问题讨论】:
-
仅供参考,我真的建议不要使用这些功能。众所周知,多行表值函数的性能很差,而带有
WHILE的函数的性能会很糟糕。 -
函数 genNum 只是技术问题,与统计问题没有任何共同之处
-
CU13 适用于 SQL Server 2019,也许您遇到的任何错误都可能已经修复。问题可能是统计数据过时,也许更新统计数据可以解决问题?
-
简单更新统计信息并不能解决问题。只有全扫描可以。由于问题甚至出现在 SQL 2008 中,我认为他们无法在 CU13 中解决它。
标签: sql-server sql-server-2019