什么类型的指数' AND'列?

时间:2015-08-14 04:55:28

标签: sql sql-server sql-server-2008

我有一个用于存储人员的表格,并希望选择该人未被标记为"已删除"的位置。我在ID列(PersonID)上有一个聚簇主键。

'已删除' column是DATETIME,可以为空,并在删除时填充。

我的查询如下:

SELECT *
FROM dbo.Person
WHERE PersonID = 100
AND Deleted IS NULL

这张桌子可以增加到大约40,000人 我是否应该有一个涵盖Deleted标志的索引?

我也可以查询以下内容:

SELECT *
FROM Task t
INNER JOIN Person p
    ON p.PersonID = t.PersonID
    AND p.Deleted IS NULL
WHERE t.TaskTypeId = 5
AND t.Deleted IS NULL

任务表估计约为150万行。

我想我需要一个涵盖两个表上的pk和已删除标志的文件?即(Task.TaskId, Task.Deleted)(Person.PersonID, Person.Deleted)

我调查索引重新考虑的原因是由于复杂程序中发生了许多死锁。我希望减少选择/写入/更新时锁定的行数,并获得性能提升。

3 个答案:

答案 0 :(得分:2)

由于您使用的是SQL Server 2008,因此最快的查询可能就是使用过滤索引。在类型为Deleted并且可以为空的DATETIME列中,您可以尝试使用此索引:

CREATE NONCLUSTERED INDEX Filtered_Deleted_Index
ON dbo.Person(Deleted)
WHERE Deleted IS NOT NULL

这将为您提供上面列出的两个用例中的最小有效集(用于查询dbo.Person以及加入Tasks)。

答案 1 :(得分:1)

你的直觉(一般来说)声音 - 包含查询所需的所有列的索引称为覆盖索引,在这种情况下需要:

CREATE INDEX Person_PersonID_Deleted ON Person(PersonID, Deleted);

通过添加Deleted列,您不太可能在索引查找方面获得很多性能优势,因为(通常)忽略搜索null,但拥有这些索引意味着可以绕过访问表完全用于Person

你也可以尝试创建:

CREATE INDEX Task_TaskTypeId_Deleted ON Task(TaskTypeId, Deleted);

将避免访问标记为“已删除”的Task行,然后只会访问未删除的行Task。但是,如果您的大多数Tasks 已删除,我不会理会此索引。

值得尝试各种索引组合,看看哪种组合能产生最佳结果。

答案 2 :(得分:1)

由于主键是<input type="checkbox" id="a1" style="display: none;" /> <label class="checkmarklabel" for="a1"></label> :checked + .checkmarklabel:before { /* put the required CSS for your font's checkmark here */ } ,因此在PersonID之后添加带有额外列的另一个索引将不会提高索引的“可选择性”,尽管可能会阻止需要通过rowid查找记录以便对{{{{{ 1}}。只有3%的记录被过滤,这没什么,所以不要在PersonID上创建另一个索引。

至于deleted表,它在很大程度上取决于Person的可选择性,即有多少记录符合标准。通常,如果选择了超过20%的记录,则顺序搜索(全表扫描)比使用行查找的索引扫描更快。对于数据分布非常大的非常大的表(例如,物理上每隔10条记录被选中),性能阈值低于10%。

因此,如果超过10-20%的任务记录是类型5,并且只删除了3%的记录,则没有索引可以提高性能,因为最快的访问计划可能是两个全表扫描的合并连接。