非聚集索引 - 键和非键

Dar*_*ong 8 index sql-server-2008 sql-server t-sql

我只是想确保我在这些概念的正确轨道上,所以任何反馈都将不胜感激。

这是我刚刚优化的查询的理论,通过反复试验和阅读 MSDN 文档的过程。

查询

DECLARE @pic_id int
SET pic_id = 1

SELECT ROW_NUMBER() OVER (ORDER BY pic_date desc) AS row_num, *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND (hidden = 0 OR pic_id = @pic_id)
Run Code Online (Sandbox Code Playgroud)

指数

CREATE NONCLUSTERED INDEX [IX_tbl_pics] ON [dbo].[tbl_pics] 
(
    [map_id] ASC,
    [deleted] ASC,
    [pic_date] DESC
)
INCLUDE ( [hidden], [pic_id] )
Run Code Online (Sandbox Code Playgroud)

pic_id上还有一个PK索引

理论

键列是这样,因为它们用于 WHERE 子句(但不用于 OR 情况)或 ORDER BY。

非键 (INCLUDE) 列也是如此,因为它们在 WHERE 中使用,但因为它们用于 OR 场景,它们不能(不能 = 不会提高性能)成为键列。

这些假设正确吗?如果没有,我错过了什么?

谢谢!

Rem*_*anu 8

您要求查询优化器生成一个可以回答查询的计划:

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;
Run Code Online (Sandbox Code Playgroud)

其余的是绒毛(包括OR pic_id = @pic_id)。这将是表扫描,这是有保证的,因为所涉及的谓词的选择性很低(我确定deleted并且hidden是 0/1,map_ip我怀疑它有任何重大影响)。唯一可以保存查询的谓词是,pic_id = @pic_id但是通过将它置于 OR 条件中,您就失去了它的机会。实际上,没有二级索引可以帮助它。添加 ROW_NUMBER 很可能是一种排序,但真正的损害是扫描。

这是一个失败的原因。提出现实的要求。


Cad*_*oux 6

主键也是聚集索引吗?如果是这样,则没有理由这样做,INCLUDE (pic_id)因为唯一聚集索引已经被用作非聚集索引中的书签。

就您所说的 OR 而言,这实际上是 WHERE 的第二部分,但您只是依靠第一个的选择性来完成大部分工作(同时依靠 INCLUDE 来避免去桌子)。

但是通过在那里有 *,你可能不得不去桌子。

另一方面,我可能不会基于单个查询设计我的索引,除非这个查询被大量使用而没有考虑更多的负载。并且仍然查看执行计划不会有什么坏处。