Mar*_*als 23 sql-server indexing
在我们的数据库中,我们有200.000行的这个表
CREATE TABLE dbo.UserTask (
UserTask_ID int NOT NULL IDENTITY (1, 1),
UserTask_SequenceNumber int NOT NULL DEFAULT 0,
UserTask_IdEntitat uniqueidentifier NOT NULL,
UserTask_Subject varchar(100) NOT NULL,
UserTask_Description varchar(500) NOT NULL,
.....
.....
CONSTRAINT [PK_UserTask] PRIMARY KEY CLUSTERED
(
[UserTask_ID] ASC
) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
我在UserTask_IdEntitat列上创建了一个索引
CREATE NONCLUSTERED INDEX IX_UserTask_IDEntitat ON dbo.UserTask
(
UserTask_IDEntitat
)
Run Code Online (Sandbox Code Playgroud)
执行以下查询,执行计划向我们显示索引on UserTask_IDEntitat用于执行查询:
SELECT UserTask_ID
FROM UserTask
WHERE UserTask_IdEntitat = @IdEntitat
ORDER BY UserTask_LastSendSystemDateTime desc
Run Code Online (Sandbox Code Playgroud)
但是如果我们在Select列表中添加另一列,则不使用索引
SELECT UserTask_ID, UserTask_SequenceNumber, UserTask_IDEntitat, ....., UserTask_Subject
FROM UserTask
WHERE UserTask_IdEntitat = @IdEntitat
ORDER BY UserTask_LastSendSystemDateTime desc
Run Code Online (Sandbox Code Playgroud)
为什么添加与主键不同的列会导致SQL Server执行计划不使用UserTask_IDEntitat列上的索引?
在此链接http://bytes.com/topic/sql-server/answers/144592-sqlsever-not-using-index之后,似乎是在列上重复过滤值的次数,它可以使我没有使用索引,但我尝试使用重复60.000次的@IdEntitat值进行查询,而其他重复次数仅为175次且结果相同,IDEntitat则忽略列上的索引.
这让我抓狂!
谢谢你的帮助.
mar*_*c_s 50
好的 - 只要您只选择索引中的列或集群键中的某些内容(通常是主键),就会使用索引,因为SQL Server可以找到所需的所有信息(UserTask_IDEntitat列和索引导航结构的叶级别中的聚簇索引列.因此,它可以SELECT直接从索引的叶级页面返回该查询所需的数据.
但是:如果您需要选择第二列,既不是索引定义中的列,也不是集群键的一部分,那么SQL Server必须对实际数据页执行所谓的书签查找.
因此,对于它在非聚簇索引中找到的每一行,它必须获取聚簇索引值,搜索聚簇索引以在该聚簇索引的叶级别查找实际数据页,然后选择一列您想.
书签查找非常适合少量点击 - 如果你选择了数千行,它们对于性能来说是完全毁灭性的.在这种情况下,SQL Server查询优化器正确地使用聚簇索引扫描 - 因为在聚簇索引中,在叶级别上,它具有所有可用的行.
所以:如果你有一个索引UserTask_IDEntitat,你有时也需要第二列UserTask_SequenceNumber- 那么你可以在你的非聚集索引中包含该列:
CREATE NONCLUSTERED INDEX IX_UserTask_IDEntitat
ON dbo.UserTask(UserTask_IDEntitat)
INCLUDE(UserTask_SequenceNumber)
Run Code Online (Sandbox Code Playgroud)
有了这个,那个附加列只存在于非聚集索引的叶级别中(它不能在WHERE子句中使用 - 它不是索引导航结构的一部分!) - 你的第二个SELECT可以再次满足非聚集索引的叶级节点 - >不需要昂贵的书签查找 - >您的索引将再次使用.
简而言之:除非您的非聚集索引具有高度选择性(例如,返回1%或更少的行),除非您的非聚簇索引是覆盖索引(包含满足特定查询所需的所有列的索引),否则更改非常高,SQL Server 不会使用你的非聚集索引.
有关更多信息:
| 归档时间: |
|
| 查看次数: |
28270 次 |
| 最近记录: |