【发布时间】:2018-05-12 15:13:48
【问题描述】:
首先,我使用的是:Microsoft SQL Server 2012 (SP1) - 11.0.3000.0 (X64)
我创建了一个如下所示的表:
create table dbo.pos_key
( keyid int identity(1,1) not null
, systemid int not null
, partyid int not null
, portfolioid int null
, instrumentid int not null
, security_no decimal(10,0) null
, entry_date datetime not null
)
keyid 是一个聚集的主键。我的表有大约 144,000 行。目前systemId波动不大,除了1之外每一行都是一样的。 现在我执行以下查询:
select *
from pos_key
where systemid = 33000
and portfolioid = 150444
and instrumentid = 639
在聚集索引扫描后返回 1 行。 [pos_key].[PK_pos_key] 执行计划说预期的行数是 1.082
SQL Server 很快建议我添加索引。
CREATE NONCLUSTERED INDEX IDX_SYS_PORT_INST
ON [dbo].[pos_key] ([systemid],[portfolioid],[instrumentid])
所以我这样做并再次运行查询。 令人惊讶的是,SQL-server 并没有使用新索引,而是再次进行相同的聚集索引扫描,但现在它声称期望 4087 行!然而,这一次并没有建议任何新的索引。
为了让它使用新索引,我做了以下操作:
- 更新表统计信息(更新统计信息)
- 更新的索引统计信息(更新统计信息)
- 已删除与此查询相关的缓存执行计划 (DBCC FREEPROCCACHE)
不走运,SQL Server 总是进行集群扫描,预计 4087 行。
索引统计如下所示:
All Density Average Length Columns
----------------------------------------------------------------------------
0.5 4 systemid
6.095331E-05 7.446431 systemid, portfolioid
1.862301E-05 11.44643 systemid, portfolioid, instrumentid
6.9314E-06 15.44643 systemid, portfolioid, instrumentid, keyid
奇怪的是,我一夜之间离开了这个,早上再次运行查询,BAMM 现在它命中了索引。我删除了索引,运行了选择,然后再次创建了索引。现在 SQL Server 又回到了预期的 4087 行和聚集索引扫描。
那么我错过了什么。该索引显然有效,但 SQL Server 不想立即使用它。
- systemId 的波动是否会造成麻烦?
- DBCC FREEPROCCACHE 是否不足以摆脱缓存的执行计划?
- SQL-Server 的方式是不是很神秘?
【问题讨论】:
-
您为每个谓词分别获得的估计行数是多少?即,如果您查看三个查询的估计计划,每个查询都有一个条件?
-
你能在你的表格中插入一个文件并共享它吗?我也尝试用与您的分布相似的分布填充表格,并且 1)没有索引建议 2)3 列的密度正确反映了情况,在我的情况下估计也是正确的
-
@MartinSmith 执行的行数如下:使用 SystemId:144270 使用 PortfolioId:26730
-
@MartinSmith 执行的行数如下所示: 使用 SystemId:144270 = 100% 使用 PortfolioId:26730 = 18,53% 使用 InstrumentId:16446 = 11,40% 这些数字恰好与如果我在按组合 ID 分组时做了最大计数()。然而,按所有 3 分组并取 count() 的最大值并没有给出 4087。然而,第三名非常接近 4074。
-
144270 * (144270/144270.0 * 26730/144270.0 * 16446/144270.0)是3047,因此基于这些值是独立的假设,您会期望这是估计值。这些值不是独立且相关的吗?
标签: sql-server indexing querying