Sql-Server
SQL Server 如何處理 DELETE WHERE EXISTS (SELECT 1 FROM TABLE)?
下面是一個有效的 TSQL 語句。但我想了解 SQL Server 是如何處理它的。
DELETE A FROM table1 WITH (NOLOCK) WHERE EXISTS ( SELECT 1 FROM table2 B WITH (NOLOCK) WHERE B.id = A.id )
因為子查詢的輸出將是一個 1 的列表。SQL Server 如何知道要刪除哪些行?
SQL Server 如何知道要刪除哪些行?
要了解它的處理方式,查看查詢的執行計劃可能更有幫助。安裝腳本在最後。
首先,讓我們將查詢稍微更改為應該引發錯誤但不會引發錯誤的內容。
DELETE A FROM table1 AS A WHERE EXISTS ( SELECT 1/0 FROM table2 B WHERE B.id = A.id );
如果你只是執行
SELECT 1/0
,你會得到一個除以零的錯誤。但是有些地方表達式存在於 parsing 查詢中,但優化器實際上並未投影。您所指的“列表”從未真正出現過。辨識要刪除的行的所有工作都是通過exists中的**where子句完成的。
當您需要了解數據流向時,從右到左閱讀計劃是正確的方法。從左到右是邏輯流。
我們有:
- 兩個表的完整掃描
- 用於匹配行的雜湊聯接
- 刪除自
table1
散列連接計算出需要刪除的行,並將符合條件的書籤值傳遞給刪除運算符。在這種情況下,書籤用於唯一標識行,因為沒有可用於從中使用鍵的聚集索引。
使用唯一的聚集索引,可以單獨使用鍵值來標識行。對於非唯一聚集索引,任何重複值都會附帶一個額外的唯一標識符,儘管這對您來說是不可見的。
設置腳本
DROP TABLE IF EXISTS table1, table2; CREATE TABLE dbo.table1 (id int NOT NULL); CREATE TABLE dbo.table2 (id int NOT NULL); INSERT dbo.table1 WITH(TABLOCK) (id) SELECT x.* FROM ( SELECT ROW_NUMBER() OVER(ORDER BY 1/0) AS n FROM sys.messages AS m ) AS x; INSERT dbo.table2 WITH(TABLOCK) (id) SELECT t.* FROM dbo.table1 AS t WHERE id % 2 = 0; SELECT TOP (100) t1.* FROM dbo.table1 AS t1; SELECT TOP (100) t2.* FROM dbo.table2 AS t2;