2

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

我想知道的是,如果我将表 A 的联接添加到表 B 并在作为聚集索引的字段上使用 where 子句(与没有额外联接的非聚集索引相反),我是否会获得性能提升)?

谢谢

4

5 回答 5

2

为了真正获得额外的性能,您最好确保您的非唯一、非聚集索引是覆盖索引(即,索引包括满足查询所需的所有列)您正在执行的查询。您可以利用SQL 2005 中引入的包含列的概念来帮助您做到这一点。

于 2010-08-04T14:08:07.090 回答
1

我做了一些测试。我有两个表 - 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。这是一个肮脏的快速示例,您应该检查自己的。

于 2010-08-04T14:58:40.140 回答
0

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

于 2010-08-04T10:21:51.177 回答
0

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

于 2010-08-04T10:16:01.920 回答
0

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

于 2010-08-04T14:25:46.967 回答