我在测试社交网站上工作。我被要求为获取用户所关注页面的查询创建索引。我是索引的新手,所以我创建了三个表并用450000条记录填充它们进行测试。除主键和索引外,这三个表是相同的。表格如图所示:
我对三个表使用相同的查询来获取用户遵循的页面。查询是:
Select top 10 PageID from UserFollowPages where UserID='something' order by ID
第一个表具有由PageID和UserID组成的唯一聚簇索引。
第二个表具有由PageID和UserID列组成的唯一非聚集索引。第二个表还有由ID列组成的聚簇索引。
第三个表具有仅由UserID构成的非聚集索引。它还有一个由ID组成的聚簇索引。
我执行三个表的查询并包含实际的执行计划。三张表的结果显示在图像中。
来自第一个表的第一个查询的结果:
第二个表中第二个查询的结果:
第三个表的第三个查询的结果:
我有两个问题:
为什么第三个查询的实际执行计划中会出现嵌套循环(内部联接)块?
我应该使用三个索引中的哪一个,知道三个查询执行的时间几乎相同(差不多0.5秒)?
答案 0 :(得分:2)
这很简单。您在UserId上有一个非聚集索引(NCI),在ID本身上有一个聚簇。
SQL Server使用NCI根据您的WHERE
- 子句过滤行。之后,索引返回所有需要的页面和行。 SQL Server现在将使用这些信息在聚簇索引中进行聚簇查找以检索所有其他所需信息(所有其他列)。如果您只想查询UserID
本身,它就会消失。
Select UserID from UserFollowPages where UserID='something'
仅仅因为所有信息都包含在一个索引中。您可以通过在NCI上使用INCLUDE(pageId, Id)
使用包含的列来避免这种情况(如果确实有必要避免这种情况)。
由于所有这些都非常小,所以确定起来并不容易。这取决于您查询表的方式。我需要更多信息。
事实上,您应该评估,您的表格写了多少,查询的频率。如果你的表写了1次并且读了100万次,那么为所有需要的用例提供更多索引是很好的。 如果你的表是100次写入和10次读取,我建议忽略索引,因为它们只是浪费你的功率和磁盘空间(在大多数情况下在这种情况下)。
鉴于这种情况,你总是使用UserID查询表,我建议你应该使用像你的第三个表中的结构。 ID
上的聚集索引(因为它是连续的)和超过UserId
的NCI,包括PageId
。