【问题标题】:Where clause on non-clustered index Vs extra join and where clause on clustered index非聚集索引上的 where 子句与聚集索引上的额外连接和 where 子句
【发布时间】:2011-03-25 04:31:20
【问题描述】:

我试图从一些 sql 查询中获得一些额外的性能,这些查询在一个字段上具有 where 子句,该字段是一个非唯一的非聚集索引,它也是表 A 中的一个外键。那个外键是表 B 的主键,是聚集索引。

我想知道的是,如果我将表 A 的连接添加到表 B 并在作为聚集索引的字段上使用 where 子句(与没有额外加入)?

谢谢

【问题讨论】:

    标签: sql-server sql-server-2005 indexing clustered-index non-clustered-index


    【解决方案1】:

    要真正获得额外的性能,最好确保您的非唯一、非聚集索引是 covering index(即,索引包括满足查询)用于您正在执行的查询。您可以利用 SQL 2005 中引入的included columns 概念来帮助您做到这一点。

    【讨论】:

      【解决方案2】:

      我做了一些测试。我有两个表 - tableA(~3000 行)和 tableB(~200 行)。他们都有列ID。 TableA:ID - pk,TableB:ID - fk,非聚集索引。

      从一张表中选择:

      SELECT 
          a.ID
      FROM
          dbo.TableA a
      WHERE 
          a.ID IN (1,5,7,9,23,45,56,546,67,32,54,676)
      

      -- 执行计划:

      |--Index Seek(OBJECT:([Database].[dbo].[TableA].[IX_TableA_ID] AS [a]), SEEK:([a].[ID]=(1) OR [a].[ID]=(5)) ORDERED FORWARD)
      

      -- 统计 IO:

      Table 'TableA'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
      

      使用两个表选择(内连接)

      SELECT 
          t.ID
      FROM
          dbo.TableA a
      INNER JOIN 
          dbo.TableB t  with(index(PK_TableBs)) ON t.ID = a.ID
      WHERE 
          t.ID IN (1,5,7,9,23,45,56,546,67,32,54,676)
      

      -- 执行计划:

        |--Nested Loops(Inner Join, OUTER REFERENCES:([t].[ID]))
             |--Clustered Index Seek(OBJECT:([Database].[dbo].[TableB].[PK_TableB] AS [t]), SEEK:([t].[ID]=(1) OR [t].[ID]=(5)) ORDERED FORWARD)
             |--Index Seek(OBJECT:([Database].[dbo].[TableA].[IX_TableA_ID] AS [a]), SEEK:([a].[ID]=[Database].[dbo].[TableB].[ID] as [t].[ID]),  WHERE:([Database].[dbo].[TableA].[ID] as [a].[ID]>=(1) AND [Database].[dbo].[TableA].[ID] as [a].[ID]<=(5)) ORDERED FORWARD)
      

      -- 统计 IO:

      Table 'TableA'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
      Table 'TableB'. Scan count 2, logical reads 4, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
      

      结果:

      第二个查询成本是第一个查询 (33%) 的 67%(相对于批次)。 此外,第二个查询需要更多读取。

      PS。这是一个肮脏的快速示例,您应该自己检查一下。

      【讨论】:

        【解决方案3】:

        我不这么认为,因为添加另一个表会涉及更多读取。但是您必须进行测试。

        【讨论】:

          【解决方案4】:

          不,按照 Frank 的说法,这需要从表 B 中读取更多页面。您说您已经在执行过滤的外键上有一个 NC 索引。您可能还会考虑通过 FK(B 的 PK)衡量对表 A 进行聚类的利弊 - 如果您通常总是通过过滤 B 来获取表 A,那么这可能会减少在 A 上获取的页面数量(但显然,可能还有其他可能受此影响的查询可能会对此产生不利影响)

          【讨论】:

            【解决方案5】:

            如果您考虑连接将如何工作 - 它将必须搜索表 A 中的 FK 列以满足连接条件 - 这是您似乎试图避免的扫描。所以我不认为有任何方法可以提高性能。

            【讨论】:

              猜你喜欢
              • 2019-02-13
              • 1970-01-01
              • 2012-08-26
              • 1970-01-01
              • 2013-08-07
              • 2020-08-04
              • 2021-09-07
              • 1970-01-01
              相关资源
              最近更新 更多