Sql-Server
如何提高對連結伺服器中相同表的 SELECT 查詢的性能
我有一個
SELECT
對連結伺服器的查詢。它看起來與此相似SELECT @Var1 = (SELECT COL1 FROM [LinkedServer].[dbo].[TableA] WHERE <Condition1>), @Var2 = (SELECT COL1 FROM [LinkedServer].[dbo].[TableA] WHERE <Condition2>), @Var3 = (SELECT COL1 FROM [LinkedServer].[dbo].[TableA] WHERE <Condition3>), ... FROM [LinkedServer].[dbo].[TableB] WHERE <Condition4>
所以這個連結伺服器中的同一個表有多個
SELECT
語句。有沒有辦法提高性能?複製TableA
到本地數據庫伺服器中的臨時表是一個壞主意嗎?尺寸TableA
很大。$$ UPDATE1 $$:更新了我的查詢
SELECT VAR_1, (SELECT SOL FROM [LinkedServer].[dbo].[TableSol] WHERE COL_1 = [TableA].COL_1 AND COL_2 = [TableA].COL_2 AND COL_A = [TableA].COL_A) AS VAR_2, (SELECT SOL FROM [LinkedServer].[dbo].[TableSol] WHERE COL_1 = [TableA].COL_3 AND COL_2 = [TableA].COL_4 AND COL_A = [TableA].COL_A) AS VAR_3, (SELECT SOL FROM [LinkedServer].[dbo].[TableSol] WHERE COL_1 = [TableA].COL_5 AND COL_2 = [TableA].COL_6 AND COL_A = [TableA].COL_A) AS VAR_4, FROM [LinkedServer].[dbo].[TableA] INNER JOIN [LinkedServer].[dbo].[TableB] ON [TableA].COL_10 = [TableB].COL_11
我花了 15 秒來執行上述查詢。我改為使用交叉表,如下所示:
SELECT VAR_1 SOL.VAR_2, SOL.VAR_3, SOL.VAR_4, FROM [LinkedServer].[dbo].[TableA] INNER JOIN [LinkedServer].[dbo].[TableB] ON [TableA].COL_10 = [TableB].COL_11 CROSS APPLY (SELECT CASE WHEN COL_1 = [TableA].COL_1 AND COL_2 = [TableA].COL_2 THEN SOL ELSE '' END AS VAR_2, CASE WHEN COL_1 = [TableA].COL_3 AND COL_2 = [TableA].COL_4 THEN SOL ELSE '' END AS VAR_3, CASE WHEN COL_1 = [TableA].COL_5 AND COL_2 = [TableA].COL_6 THEN SOL ELSE '' END AS VAR_4 FROM [LinkedServer].[dbo].[TableSol] WHERE COL_A = [TableA].COL_A ) AS SOL (VAR_2, VAR_3, VAR_4)
但是我花了更長的時間(> 10分鐘,我只是停下來,因為它沒有完成)。我錯過了什麼?
可以使用交叉表重寫查詢,以避免多次命中 TableA:
DECLARE @TableA TABLE (col1 int, col2 int); DECLARE @TableB TABLE (col3 int, col4 int); INSERT INTO @TableA VALUES (1,1), (2,2), (3,3), (4,4); INSERT INTO @TableB VALUES (1,1), (2,2), (3,3), (4,4); DECLARE @Var1 int, @Var2 int, @Var3 int; SELECT @Var1 = CA.var1, @Var2 = CA.var2, @Var3 = CA.var3 FROM @TableB AS TB CROSS APPLY ( SELECT SUM(CASE WHEN col2 = 1 THEN col1 END) AS var1, -- ^^ This is <Condition1> SUM(CASE WHEN col2 = 2 THEN col1 END) AS var2, -- ^^ This is <Condition2> SUM(CASE WHEN col2 = 3 THEN col1 END) AS var3 -- ^^ This is <Condition3> FROM @TableA AS TA ) AS CA(var1, var2, var3) WHERE TB.col3 > 2 -- <Condition4> SELECT @Var1, @Var2, @var3
這應該使它更快。如果沒有,請發布執行計劃,以便我們進一步調查。
您可以使用 4 部分名稱表示法在連結伺服器上將查詢作為傳遞查詢執行,並且
sp_executesql
:DECLARE @var1 int, @var2 int, @var3 int, @var4 int; EXEC [linkedserver].[databasename].sys.sp_executesql N' SELECT @var1 = VAR_1, @var2 = ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_1 AND COL_2 = [TableA].COL_2 AND COL_A = [TableA].COL_A), @var3 = ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_3 AND COL_2 = [TableA].COL_4 AND COL_A = [TableA].COL_A), @var4 = ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_5 AND COL_2 = [TableA].COL_6 AND COL_A = [TableA].COL_A), FROM [dbo].[TableA] INNER JOIN [dbo].[TableB] ON [TableA].COL_10 = [TableB].COL_11 ', N'@var1 int OUTPUT, @var2 int OUTPUT, @var3 int OUTPUT, @var4 int OUTPUT', @var1 OUTPUT, @var2 OUTPUT, @var3 OUTPUT, @var4 OUTPUT; SELECT @var1, @var2, @var3, @var4;
如果您不需要分配給變數,則可以使用以下語法:
EXEC [linkedserver].[databasename].sys.sp_executesql N' SELECT VAR_1, ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_1 AND COL_2 = [TableA].COL_2 AND COL_A = [TableA].COL_A), ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_3 AND COL_2 = [TableA].COL_4 AND COL_A = [TableA].COL_A), ( SELECT SOL FROM [dbo].[TableSol] WHERE COL_1 = [TableA].COL_5 AND COL_2 = [TableA].COL_6 AND COL_A = [TableA].COL_A), FROM [dbo].[TableA] INNER JOIN [dbo].[TableB] ON [TableA].COL_10 = [TableB].COL_11 '