內連接如何優化?
我有一張桌子,在某些情況下有雙記錄。
在表中,我有以下列:
- id(身份列)
- action_id
- session_id
- row_id
- 時間戳
- …以及更多記錄。
我需要為特定的
id
.一個雙記錄
action_id=11
是 whenaction_id=12
和session_id
,row_id
和timestamp
是相同的。表定義
假設我的表創建如下。(無附加索引)
CREATE TABLE table_name ( [id] BIGINT IDENTITY(1,1) PRIMARY KEY, [session_id] BIGINT default @@SPID, [row_id] BIGINT default 0, [timestamp] DATETIME default CURRENT_TIMESTAMP, [action_id] SMALLINT NOT NULL, [value1] NVARCHAR(max) NULL, [value2] NVARCHAR(max) NULL, [value3] NVARCHAR(max) NULL)
選擇語句
我目前的查詢是:
SELECT d.* FROM [table_name] d INNER JOIN [table_name] i ON d.[session_id] = i.[session_id] AND d.[row_id] = i.[row_id] AND d.[timestamp] = i.[timestamp] WHERE d.[action_id] = 12 AND i.[action_id] = 11 AND i.[id] = X -- where X is the input
問題
我希望查詢盡可能快,所以我的問題是:
where
如果我在連接中移動條件有區別嗎?SELECT d.* FROM [table_name] d INNER JOIN [table_name] i ON d.[session_id] = i.[session_id] AND d.[row_id] = i.[row_id] AND d.[timestamp] = i.[timestamp] AND d.[action_id] = 12 AND i.[action_id] = 11 WHERE i.[id] = X -- where X is the input
timestamp
我應該為,row_id
和session_id
列添加索引嗎?- 首先會發生什麼,
JOIN
表格或過濾結果WHERE
?- 以下查詢更好嗎?
SELECT d.* FROM ( (SELECT * FROM [table_name] WHERE [id] = X AND action_id = 11) i INNER JOIN (SELECT * FROM [table_name] WHERE [id] > X AND action_id = 12) d ON d.[session_id] = i.[session_id] AND d.[row_id] = i.[row_id] AND d.[timestamp] = i.[timestamp] )
- 我還能做些什麼來讓它執行得更快?
如果我將 where 條件放在 join 部分有區別嗎?
在你的情況下,不。
Optimizer
足夠聰明,可以理解。
Where Clause
進一步對 JOIN 產生的內容進行過濾。
INNER JOIN
:這裡WHERE clause
沒有太多要放置的過濾器。應用過濾器的結果集較小。事實上,在 的情況下,將orINNER JOIN
放在哪裡都沒有關係。足夠聰明,可以理解。沒有性能差異。condition``JOIN``WHERE``Optimizer
OUTER JOIN
:這裡WHERE clause
有更大的結果集來應用過濾器。由於Where clause
有更大的結果集要過濾掉,因此Filter
在條件下盡可能多的有意義JOIN ON
,以便產生更小的結果集。如果在右表中應用 where 條件,則
LEFT JOIN
相當於INNER JOIN
儘管在大多數情況下
OUTER JOIN
,優化器足夠聰明,可以在內部理解並將其轉換WHERE
為ON
。它取決於範例,特別是
complex query
涉及數據。檢查查詢計劃並相應地確定條件large volume
總是明智的。WHERE
您應該使用
predicate
在ON
邏輯上關聯連接表的列。如果是
filter
條件,則在Where
子句中使用它。我應該為時間戳、row_id、session_id 添加索引嗎?
是的。創造
composite Non clustered index
。選擇Clustered index([id])
是完美的。Create NonClustered Index NCI_Table_Action_Row_Session_Timestamp on table_name(action_id,row_id,session_id,Timestamp) GO
注意列的順序。窄列應該在最左邊。沒有意義 in
Covering index
asnvarchar(max)
are not use incovering index
。我還能做些什麼來讓它執行得更快?
我認為而不是
INNER
使用。EXISTS
不要使用*
SELECT d.[id] , [session_id] , [row_id] , [timestamp] , [action_id] , [value1] , [value2] , [value3] FROM [table_name] d where(select 1 from [table_name] i where i.[id] = X -- where X is the input AND i.[action_id] = 11 ---- where 11 is the input AND d.[action_id] = i.[action_id]+1 --12 ---- if 12 is input then it is more good AND d.[session_id] = i.[session_id] AND d.[row_id] = i.[row_id] AND d.[timestamp] = i.[timestamp] )