【发布时间】:2021-04-19 20:01:09
【问题描述】:
我有一个包含大约 2 亿条记录的事务表,一个主键聚集在 Id 和 2 个索引上:
- IX_SiloId_ChangedTime_IncludeTime
- IX_SiloId_Time_IncludeContent
在执行实际查询以更新统计信息之前,我会运行这两条语句
Update STATISTICS dbo.[Transaction] IX_SiloId_ChangedTime_IncludeTime WITH FULLSCAN
Update STATISTICS dbo.[Transaction] IX_SiloId_Time_IncludeContent WITH FULLSCAN
这是我的查询:
DECLARE @Query SiloTimeQueryTableType -- (SiloId, Time) with primary key clustered on SiloId
INSERT INTO @Query VALUES
(1, '2020-12-31'), -- 1000 total values, though it's still the same problem with just one
SELECT t.*
FROM [Transaction] t
INNER JOIN @Query q
ON t.SiloId = q.SiloId
WHERE
t.Time >= q.Time
现在无论出于何种原因 Sql Server 选择了IX_SiloId_ChangedTime_IncludeTime,都会发生什么。然后它需要永远。如果我使用WITH (INDEX(IX_SiloId_Time_IncludeContent)),我会立即得到结果。
正确的索引在这里很明显,但是 SQL Server 选择了一个甚至没有在 Time 上建立索引的索引。
我无法理解这种行为,但从我阅读的内容来看,最好避免对索引的提示,尽管我在制作这个索引时考虑到了这个查询。
所以问题是:我该怎么做才能弄清楚为什么 SQL Server 更喜欢“错误”的索引,即使存在更好的索引并且我只是运行完整的统计更新?
我创建了一个临时表,因为许多人认为 TVP 失败,但结果是一样的:
CREATE TABLE #Query
(
SiloId bigint NOT NULL PRIMARY KEY CLUSTERED,
Time datetime2(7) NOT NULL
)
执行计划:
https://www.brentozar.com/pastetheplan/?id=rJOt3G00P
https://www.brentozar.com/pastetheplan/?id=ByFshGAAP(这个是live,因为太长了)
指数:
CREATE NONCLUSTERED INDEX [IX_SiloId_Time_IncludeContent] ON [dbo].[Transaction]
(
[SiloId] ASC,
[Time] ASC
)
INCLUDE([SiloContent]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_SiloId_ChangedTime_IncludeTime] ON [dbo].[Transaction]
(
[SiloId] ASC,
[ChangedTime] ASC
)
INCLUDE([Time]) WITH (STATISTICS_NORECOMPUTE = OFF, DROP_EXISTING = OFF, ONLINE = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
GO
【问题讨论】:
-
您为什么要向 SO 和 DBA 发布相同的问题?我看到你删除了你之前关于讨论使用 tvp / table 变量的同一主题的问题。
-
表变量没有统计信息,这可能是SQL Server选择错误索引的原因。我建议你改用临时表,看看在这种情况下 SQL Server Server 是否选择了正确的索引
-
@SMor 因为这是 2 个不同的网站,显然有不同的人在回答?
-
@JesúsLópez 我已经读过这个,我实际上已经尝试过使用临时表。结果是一样的。似乎实际上在打开实时统计信息后它会进行聚集索引扫描......
-
能否请您发布执行计划?您可能想使用brentozar.com/pastetheplan。请显示索引和表定义。
标签: sql sql-server indexing sql-execution-plan