我试图从一些 sql 查询中获得一些额外的性能,这些查询在字段上具有 where 子句,该字段是非唯一非聚集索引,它也是表 A 中的外键。该外键是主键在表 B 上,并且是聚集索引。
我想知道的是,如果我将表 A 的联接添加到表 B 并在作为聚集索引的字段上使用 where 子句(与没有额外联接的非聚集索引相反),我是否会获得性能提升)?
谢谢
我试图从一些 sql 查询中获得一些额外的性能,这些查询在字段上具有 where 子句,该字段是非唯一非聚集索引,它也是表 A 中的外键。该外键是主键在表 B 上,并且是聚集索引。
我想知道的是,如果我将表 A 的联接添加到表 B 并在作为聚集索引的字段上使用 where 子句(与没有额外联接的非聚集索引相反),我是否会获得性能提升)?
谢谢
为了真正获得额外的性能,您最好确保您的非唯一、非聚集索引是覆盖索引(即,索引包括满足查询所需的所有列)您正在执行的查询。您可以利用SQL 2005 中引入的包含列的概念来帮助您做到这一点。
我做了一些测试。我有两个表 - 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。这是一个肮脏的快速示例,您应该检查自己的。
不,按照弗兰克的说法,这需要从表 B 中读取更多页面。您说您已经在执行过滤的外键上有一个 NC 索引。您还可以考虑通过 FK(B 的 PK)权衡表 A 集群的利弊 - 如果您通常总是通过过滤 B 来获取表 A,那么这可能会减少在 A 上获取的页面数量(但显然,可能有其他可能受此影响的查询可能会对此产生不利影响)
我不这么认为,因为添加另一个表会涉及更多读取。但是你必须进行测试。
如果您考虑连接将如何工作 - 它必须在表 A 中搜索 FK 列以满足连接条件 - 这就是您似乎试图避免的扫描。所以我不相信有任何方法可以提高性能。