非聚集索引-键和非键


8

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

这是我根据刚刚经过优化的查询通过反复试验并阅读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)

索引

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

pic_id上还有一个PK索引

理论

键列之所以如此,是因为它们用于WHERE子句(但不用于OR情况)或and ORDER BY。

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

这些推论正确吗?如果没有,我想念什么?

谢谢!

Answers:


8

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

SELECT *
FROM tbl_pics
WHERE deleted = 0 AND map_id = 1 AND hidden = 0;

其余为绒毛(包括OR pic_id = @pic_id)。由于所涉及谓词的选择性低(这是肯定的deleted并且hidden为0/1,并且map_ip我怀疑它是否会产生重大影响),因此这将是表扫描,可以保证。唯一可以保存查询的谓词是pic_id = @pic_id但是通过将其置于“或”条件下,您杀死了它的机会。实际上,没有任何二级索引可以提供帮助。ROW_NUMBER的添加很可能会带来某种影响,但真正的损坏是扫描。

这是一个失败的原因。提出切合实际的要求。


6

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

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

但是,如果在其中带有*,则可能还是要去桌子。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.