问题是关于MS SQL Server 2008 +。
有桌子(比方说,5-10M行)
CREATE NONCLUSTERED INDEX [IX_Persons_LastName_FirstName]
ON [Test].[Persons] ([LastName] ASC, [FirstName] ASC)
使用索引
SELECT [FirstName],[LastName],[BirthDate]
FROM [Test].[Persons] WHERE [LastName] = 'Decker'
执行简单查询,如
"features": [
{
"geometry": {
"coordinates": [
16.91828856,
52.3838415
],
"type": "Point"
},
"id": "ROLN04",
"type": "Feature",
"properties": {
"zone": "A",
"route_type": "3",
"headsigns": "238",
"stop_name": "Rolna"
}
},
{
"geometry": {
"coordinates": [
16.88799654,
52.40252503
],
"type": "Point"
},
"id": "RJNJ01",
"type": "Feature",
"properties": {
"zone": "A",
"route_type": "3",
"headsigns": "251",
"stop_name": "Rondo Jana Nowaka-JezioraĹskiego"
}
},
我看到,使用 Index Seek 运算符,当键不在统计直方图精确值中时,估计的行与实际行的差异很大。
对于某些特定键,它可以是大约15个估计行vs 10k实际行。
在这种情况下似乎“Estimated rows”值直接取自AVG_RANGE_ROWS以获得相应的间隔(即下一个直方图值)。
这是预期的行为吗?我的意思是,SQL Server“知道”该值是不确切的并在计算查询成本中使用这一事实,或者它是一个潜在的错误查询计划问题?
尝试使用SQL2008R2,2012,2014(全部使用OLD基数估算器)据我所知,新CE仅在处理查询中的多个表时才会更改。尝试很有意思,但我还没有。
答案 0 :(得分:0)
我在这个问题上做了一些工作并明确表达了。
简短回答:好吧,对我感到羞耻。这正是统计工作的方式。在我的情况下,额外的过滤统计数据将赢感谢您的评论,他们开始检查非常有用。
答案很长: “问题”在于数据密钥分配。我在直方图中填充了所有200个步骤,它无法收集有关确切非常常见值的更多信息。超过500k的相对罕见的不同值,它给我们带来了明显的效果(对我而言)。
我制作了一个简单的示例脚本,演示了类似的行为:
CREATE TABLE [TestStatistics] (
[Id] [INT] IDENTITY (1,1) PRIMARY KEY,
[Val] [INT] NOT NULL
)
GO
--Insert 200k rows with ~60k distinct values
insert into TestStatistics (Val) VALUES (CHECKSUM (newid())%30000)
go 200000
--Insert 100k rows with ~600 distinct values, that are multiples of 100
insert into TestStatistics (Val) VALUES (CHECKSUM (newid())%300*100)
GO 100000
create nonclustered index IX_TestStatistics_Val on TestStatistics(Val ASC)
GO
所以,我已经插入了300k总行,其中有大约60k个不同的值,这意味着表中的密度约为0.2。而且我有“特殊”的100k行,它们填充了~600个不同的值 - 100的倍数。也就是说,这些行中的任何行都会遇到~166次。 现在统计数据看起来像这样:
现在,如果我采用100的倍数,直方图中没有(例如,7500),我将估计4.5-5.5行和近166个实际行。估计值实际上只是直方图中的下一个AVG_RANGE_ROWS值(对于7500 - 在Val = 7800)。
现在,如果我收集一些额外的统计数据,比如
CREATE STATISTICS ST_TestStatistics_0_10000
ON TestStatistics(Val) WHERE Val>=0 AND Val<10000
我会得到另一个查询计划: