dev*_*dev 5 sql-server clustered-index index-tuning nonclustered-index sql-server-2016
我正在尝试加快表格速度,当我进行实验时,我遇到了这种(我认为是)奇怪的情况。我创建了一个聚集索引和一个非聚集索引,它们应该是相同的。然而,当我对表运行查询时,我发现 SQL Server 总是希望使用非聚集索引而不是匹配的聚集索引。最重要的是,当需要时,SQL Server 将正确地对非聚集索引执行索引查找,但始终对聚集索引执行扫描。
为什么SQL Server更喜欢非聚集索引?
我怎样才能重写这个,以便我仍然可以提高性能,但只有聚集索引?
我有以下表结构:
CREATE TABLE [dbo].[Variables](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[Header] [varchar](255) NULL,
[FullVariables] [varchar](max) NULL
)
Run Code Online (Sandbox Code Playgroud)
聚集索引:
ALTER TABLE [dbo].[Variables] ADD CONSTRAINT [PK_Variables] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
Run Code Online (Sandbox Code Playgroud)
非聚集索引:
CREATE UNIQUE NONCLUSTERED INDEX [NonClusteredIndex-20190307-091011] ON [dbo].[Variables]
(
[ID] ASC
)
INCLUDE ( [Header],
[FullVariables])
Run Code Online (Sandbox Code Playgroud)
我目前的知识使我相信,在这种情况下,这两个索引都应包含以相同方式布置的数据,其中 [ID] 是关键列,然后 [Header] 和 [FullVariables] 作为索引中包含的额外数据成为指针。如果您有一些可以链接的知识来源,我非常渴望阅读更多内容。
我应该指出,我并不总是想要搜索,并且我知道在某些情况下扫描更好(否则为什么会有它)。由于行大小(数百万)乘以varchar(MAX)
(其中包含长度超过 16000 个字符的字符串),该表包含大约 60GB 的数据。在插入到表中之前,会进行扫描以确保没有插入重复项(匹配 onHeader
来消除和 on FullVariables
)。然后,该表将在需要查找的 ID 字段上的多个视图中连接起来。
如果 SQL Server 有两个索引可供选择,这两个索引都满足(“覆盖”)查询并提供定位和/或排序行的最佳路径,那么您应该将其视为抛硬币。但事实并非如此......我相信这里(也许是我,这里和这里)进行了一些研究,表明它选择了最新创建的或按字母顺序排列的第一个或其他任意的东西。
然而,如果我们所说的抛硬币涉及到非聚集索引和聚集索引之间的选择,并且这两个索引都正确满足查询,那么 SQL Server 将始终倾向于非聚集索引。为什么?因为它保证不比聚集索引宽。不考虑与聚集索引宽度完全相同的边缘情况。
您应该查看每个执行计划涉及的成本,并确认 SQL Server 对非聚集索引的估计成本 <= 对聚集索引的成本。如果您可以展示一个反例,其中选择非聚集索引,即使其估计成本高于聚集索引,请这样做。
归档时间: |
|
查看次数: |
2083 次 |
最近记录: |