2

我想要從一些SQL查詢中獲得一些額外的性能,這些查詢在一個非獨特的非集羣索引,它也是表A中的外鍵。該外鍵是表B上的主鍵,並且是聚集索引。關於非聚集索引Vs的where子句額外連接和where子句的聚集索引

我想知道的是,如果我添加從表A到表B的連接,並且在聚集索引的字段上有where子句(與非聚集索引相反),我會獲得性能增益沒有額外的連接)?

感謝

回答

0

我不這麼認爲,如添加另一個表將涉及更多的讀取。但是你必須測試。

0

否按照Frank的說法,這需要從表B中讀取更多頁面。您說您已對執行過濾的外鍵擁有NC索引。你也可以考慮用FK(B的PK)來衡量表A的聚集優點和缺點 - 如果你通常總是通過在B上過濾來獲取表A,那麼這可以減少在A上獲取的頁的數量(但顯然,可能會有其他的查詢可能會受到這個影響,這可以算作對此)

2

要真正消除多餘的性能,你最好確保你的非唯一的非聚集索引是一個covering index(即索引包含滿足查詢所需的所有列)。您可以利用SQL 2005中引入的included columns這一概念來幫助您做到這一點。

0

如果您考慮連接的工作方式 - 它必須在表A中搜索FK列以滿足連接條件 - 這是您似乎試圖避免的掃描。所以我不相信這有可能改善表現。

1

我做了一些測試。我有兩個表 - tableA(~3000行)和tableB(~200行)。他們都有專欄ID。表A:ID-pk,表B: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) 

- STATISTICS 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。這是骯髒的快速例子,你應該檢查你自己的。