標籤:archive logs 中文 not insert 判斷 har concat 就是
前言:
根據計劃,本文開始講述另外一個操作符串聯(Concatenation),讀者可以根據這個詞(中英文均可)先幻想一下是幹嘛的。其實還是挺直觀,就是把東西連起來,那麼下面我們來看看到底連什嗎?怎麼連?什麼時候連?
簡介:
串聯操作符既是物理操作符,也是邏輯操作符,在中文版SQL Server的圖形化執行計畫中稱為“串聯”,在其他格式及英文版本中稱為“Concatenation”。其表徵圖為:
,它掃描多個輸入並返回每個掃描的行。通常用於實現T-SQL中的UNION ALL。它可以有多個輸入,但只有一個輸出,就如多個集合UNION ALL一樣,最終返回一個結果集,注意這裡一直使用“集合/集”,關聯式資料庫是基於集合論的,所以使用關聯式資料庫時要以集合的思維去考慮問題。
在執行計畫中的每個操作符,都要實現三個方法/函數:Init()、GetNext()和Close()。前面說了,串聯操作符是其中一種可以接受多個輸入的操作符,這些輸入會在Init()方法中處理。
在Init()方法中,串聯初始化然後建立所需的資料結構。然後在運行GetNext()方法讀取輸入集中的第一行及後續行,直到把輸入集合裡面的所有資料讀取完畢為止。
環境搭建:
下面建立一個測試表並迴圈插入10000行資料。
USE tempdb
GO
IF OBJECT_ID(‘TEST‘, ‘U‘) IS NOT NULL
DROP TABLE TEST
GO
CREATE TABLE Test (
ID INT Identity(1, 1) PRIMARY KEY
,Nome VARCHAR(250) DEFAULT NewID()
)
GO
SET NOCOUNT ON
GO
INSERT INTO Test DEFAULT
VALUES
GO 10000
串聯示範:
前面提到,串聯主要用於實現T-SQL的UNION ALL ,那麼現在就來看看UNION ALL的情況:
開啟實際執行計畫並運行下面語句:
SELECT * FROM TEST
UNION ALL
SELECT * FROM TEST
UNION ALL
SELECT * FROM TEST
UNION ALL
SELECT * FROM TEST
執行計畫如下:
如果使用SET SHOWPLAN_TEXT ON來查看的話可以看到如下結果:
這個圖的含義是把4個“Clustered Index Scan”的結果塞到一個結果集,然後調用Init()和GetNext()方法去遍曆這些資料,然後輸出。另外需要說明的是這個操作符是根據T-SQL中結果集的出現順序來處理的,為了證明這個想法,我們來改寫一下語句:
SET SHOWPLAN_TEXT ON
GO
SELECT * FROM TEST
WHERE ID<100
UNION ALL
SELECT * FROM TEST
WHERE ID BETWEEN 101 AND 1000
UNION ALL
SELECT * FROM TEST
WHERE ID BETWEEN 1001 AND 5000
UNION ALL
SELECT * FROM TEST
WHERE ID >5001
然後看看輸出:
對比一下參數可得每個Clustered Index Seek的順序和語句的出現順序是一致的。另外讀者可能留意到每行最後的ORDERED FORWARD,其含義是掃描索引的順序是按照叢集索引的順序並向前掃描。
關於這個話題可以看看SQL Server技術內幕主要作者Kalen Delaney的部落格:Ordered Seeks and Scans。
總結:
本文主要示範了串聯操作符的情況,並且主要以T-SQL中的UNIONALL來觸發。由於目前沒有任何資料顯示是否僅UNION ALL才會使用,所以這裡也不做絕對的判斷,讀者只需要知道這個操作符的含義、常見情景即可。另外讀者可以使用UNION 來檢查執行計畫,實際上UNION 是不用串聯的,因為它本質上需要去重,所以使用不同的操作符來實現,比如Merge Join,在後續再介紹。
SQL Server 執行計畫操作符詳解(2)——串聯(Concatenation )