为什么嵌套循环块会出现在实际的执行计划中?

Why nested loop block appear in acutal exection plan?

我在一个测试社交网站上工作。我被要求为查询创建索引,以获取用户 follows.I 对索引不熟悉的页面,因此我创建了三个 table 并在其中填充了 4500000 条记录以进行测试。三个table除了主键和索引外其他都是一样的。 tables如图所示:

我对三个 table 使用相同的查询来获取用户关注的页面。查询是:

Select top 10 PageID from UserFollowPages where UserID='something' order by ID  

第一个 table 有一个由 PageID 和 UserID 组成的唯一聚集索引。

第二个 table 有一个由 PageID 和 UserID 列组成的唯一非聚集索引。第二个 table 也有由 ID 列组成的聚簇索引。

第三个 table 具有仅由 UserID 组成的非聚集索引。它还有一个由ID组成的聚簇索引。

我执行三个 table 的查询并包括实际执行计划。三个 table 的结果如图所示。

第一个 table 中第一个查询的结果:

来自第二个 table 的第二个查询的结果:

第三个 table 的第三个查询的结果:

我有两个问题:

  1. 为什么第三个查询的实际执行计划中会出现嵌套循环(内连接)块?

  2. 我应该使用三个索引中的哪一个,知道三个查询执行的时间几乎相同(几乎 0.5 秒)?

1。嵌套循环

很简单。您在 UserId 上有一个非聚集索引 (NCI),在 ID 本身上有一个聚集索引。

SQL 服务器使用 NCI 根据您的 WHERE 子句过滤您的行。之后,索引 returns 所有需要的页面和行。 SQL 服务器现在将使用这些信息在聚簇索引中进行聚簇查找,以检索所有其他需要的信息(所有其他列)。如果您只想查询 UserID 本身,它就会消失。

Select UserID from UserFollowPages where UserID='something'

只是因为所有信息都包含在一个索引中。您可以通过在 NCI 上使用包含的列使用 INCLUDE(pageId, Id) 来避免这种情况(如果确实有必要避免它)。

2。使用哪一个

由于都非常小,不好判断。这取决于您查询 table 的方式。为此,我需要更多信息。

其实你应该评估一下,你的table写了多少,查询的频率是多少。如果您的 table 被写入 1 次并读取 100 万次,那么最好为所有需要的用例提供更多索引。 如果您的 table 写入了 100 次,读取了 10 次,我建议您忽略索引,因为它们只会浪费您的电量和磁盘 space(在大多数情况下都是这种情况)。

鉴于您总是使用 UserID 查询 table,我建议您应该使用第三个 table 中的结构。 ID 上的聚集索引(因为它是顺序的)和 UserId 上的 NCI,包括 PageId.