Sql-Server

內連接如何優化?

  • November 19, 2019

我有一張桌子,在某些情況下有雙記錄。

在表中,我有以下列:

  • id(身份列)
  • action_id
  • session_id
  • row_id
  • 時間戳
  • …以及更多記錄。

我需要為特定的id.

一個雙記錄action_id=11是 whenaction_id=12session_id,row_idtimestamp是相同的。

表定義

假設我的表創建如下。(無附加索引)

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_idsession_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,優化器足夠聰明,可以在內部理解並將其轉換WHEREON

它取決於範例,特別是complex query涉及數據。檢查查詢計劃並相應地確定條件large volume總是明智的。WHERE

您應該使用predicateON邏輯上關聯連接表的列。

如果是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 indexas nvarchar(max)are not use in covering 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] 

  )

引用自:https://dba.stackexchange.com/questions/253493