微軟BI 之SSIS 系列 - Merge, Merge Join, Union All 合併組件的使用以及Sort 排序組件同步異步的問題

開篇介紹

SSIS Data Flow 中有幾個組件能夠實現不一樣數據源的數據合併功能,好比 Merger, Merge Join 和 Union All。它們的功能比較相似,同時也比較容易混淆,下面是對它們之間的區別的對比總結。html

 

下面經過三個 Data Flow 來演示這三個組件的使用以及相關的配置。數據庫

測試數據源 -緩存

第一個數據源是一張表測試

USE BIWORK_SSIS
GO

-- Merge demo table
IF OBJECT_ID('DEMO_MG_Customer','U') IS NOT NULL
DROP TABLE DEMO_MG_Customer
GO

CREATE TABLE DEMO_MG_Customer
(
  CustomerID INT PRIMARY KEY,
  CustomerCompany NVARCHAR(255),
  CustomerName NVARCHAR(20),
  CustomerAddress NVARCHAR(255)
)

INSERT INTO DEMO_MG_Customer VALUES
(1,'HFBZG','Allen,Michael','Obere Str. 0123'),
(2,'MLTDN','Hassall, Mark','Avda. de la Constitución 5678'),
(3,'KBUDE','Peoples, John','Mataderos  1000')

SELECT * FROM DEMO_MG_Customer

第二個數據源是一個文本文件spa

ID,Company,CustomerName,Title,Addresscode

1,'NRZBB','Allen,Michael','Sales Representative','Obere Str. 0123'orm

2,'MLTDN','Hassall, Mark','Owner','Avda. de la Constitución 5678'htm

3,'KBUDE','Peoples, John','Owner','Mataderos  7890'blog

4,'HFBZG','Arndt, Torsten','Sales Representative','7890 Hanover Sq.'排序

5,'HGVLZ','Higginbotham, Tom','Order Administrator','Berguvsvägen  5678'

示例一 - 使用 Merge 來合併數據

  • 上面已經說了 Merge 的特色-
  • 輸入數據源 - 兩個
  • 輸入數據源 - 表或者文件等
  • 合併時要求元數據相同,數據類型相同
  • 合併前須要排序

 

合併操做相似於 SQL 語句中的 UNION ALL。

OLE_SRC_Customer - OLE DB Source 中指定的數據源來自 BIWORK_SSIS 數據庫中的 dbo.DEMO_MG_Customer 表。

表中的 5 個列都將做爲輸出列向下輸出。

FF_SRC_Customer (Flat File Source) 的 Flat File Connection Manager 指向文本文件源。而且要注意 Text qualifier 是', 由於要注意到文本文件中位於 '  ' 之間的纔是真正要處理的文本。

1,'NRZBB','Allen,Michael','Sales Representative','Obere Str. 0123'

而且指明文本文件中的第一行是列標題。

逗號分割列

在這裏要注意的是文本文件中 ID 的數據類型指定 DT_I4 來映射 SQL Server 數據庫中的INT 類型,不然兩個數據源一旦有一個列數據類型不一致的話,那麼合併操做時就會出現錯誤。

其它字符串用 DT_WSTR 便可,由於要和數據庫中的 NVARCHAR 數據類型匹配。

注意在 Flat File Source 向下輸出的時候並無選擇 Title, 由於這一列在 Input Table Source 中並不存在。在合併兩個來自不一樣數據源的時候,咱們要求兩邊的元數據一致,即列的數量和類型也應該一致。

由於自己 ID 就是有序的,因此爲了演示的效果選擇 CustomerName 做爲排序列,兩邊的源的拍序列也應該選擇一致。

Merger Transformation 列出了輸出的列,兩個輸入源而且顯示了它們的排序列,最終輸出的結果也會按照 CustomerName 排序的結果來輸出。

Merge 以後來自於兩個不一樣數據源的數據就合併到了一塊兒,而且 CustomerID = 2 的數據分別來自兩個數據源,內容也是一致的,但並無在合併的時候刪除重複的數據,這相似於 SQL 語句中的 UNION ALL 的操做,保留了重複項。

示例二 - 使用 Merge Join 組件合併數據

Merge Join 相似於 SQL 中的 Full/Left/Inner Join 等操做,由於不須要兩邊數據源的元數據一致。可是,它也要求左右兩邊的數據源排序,而且排序列必須包含後面使用到的 JOIN 列。

前面的配置和上一個例子中同樣,只是排序列改爲了 CustomerID,只看 Merge Join 部分。

除了 Inner Join 外,還有 Full Join 和 Left Outer Join 等同於 SQL 中的 Inner Join/Full Join/Left Join 等操做。

看上面圖片中顯示了左右兩邊的數據源,其中 Join Key 必須包含在排序列中。在左邊的表數據源中有4個輸出列,與右邊文件中的 Title 輸出列共同組成了5個輸出列。

若是使用 SQL 語句來表示這裏的邏輯,能夠理解成-

SELECT tbl.CustomerID,
            tbl.CustomerCompany,
            tbl.CustomerName,
            tbl.CustomerAddress,
            ff.Title
FROM ST_TBL_Customer AS tbl
INNER JOIN ST_FF_Customer AS ff
ON tbl.CustomerID = ff.ID

從這裏看出 Inner Join 能關聯上3條數據,其中 Title 列來源於文件數據源。

在這裏,也可使用 Merge Join 組件完成對已存在的數據進行更新,對不存在的數據進行插入操做。好比可使用 Left Outer Join, 假設以左表爲目標表的話,那麼就可以利用關聯上 ID 的右文件數據源來更新左表,關聯不上的就做爲新數據插入到左表中。只須要在 Merge Join 下加一個 Conditional Split 組件來判斷便可,能夠參考個人另外一篇文章 -

SSIS 系列 - Lookup 組件的使用與它的幾種緩存模式 - Full Cache, Partial Cache, NO Cache

示例三 - 使用 UNION ALL 組件合併數據

UNION ALL 組件與上面兩個組件最大的區別就是,一能夠合併兩個以上的數據源,二是不須要對數據源進行排序。

這個示例中有三個數據源,前兩個和上面示例中的配置同樣,第三個數據源和第二個數據源實質上相同,都是指向同一個數據表。

直接看 UNION ALL 組件的配置,很是的簡單。

看到輸出列了嗎? 默認狀況下將第一個文件數據源的列做爲默認的整個組件的輸出列,若是後面的數據源沒有這些列的話,那麼就忽略掉,其它的列再一一設置匹配一下,固然數據類型應該一致。

輸出的結果以下,有重複的數據而且也未排序。

三個組件各自不一樣的特色

簡單的能夠概括一下什麼時候應該選擇 Merge, Merge Join 和 Union All 組件來合併不一樣數據源的數據呢?

  • 若是有兩個以上的數據源 - UNION ALL
  • 若是隻有兩個數據源,而且是從兩個不一樣數據源基於一些關聯條件各取一部分數據 - Merge Join
  • 若是隻有兩個數據源,目的爲了合併而非關聯 - UNION ALL/Merge
  • 若是隻有兩個數據源,目的只爲了合併但不須要輸出的結果排序 - UNION ALL
  • 若是隻有兩個數據源,目的只爲了合併但須要輸出的結果排序 - Merge

Asynchronous Transformation VS  Synchronous Transformation 

固然,除此以外還有些細節須要知道的是 - 儘可能避免使用 Sort 排序組件,緣由在於 Sort 排序組件被稱之爲 Asynchronous Transformation。

Asynchronous Transformation 非同步轉換 - Blocked Transformation 阻塞轉換。Sort 排序組件就屬於這一類,和它相同的還有 Pivot 組件。

它們處理數據的過程是先從上游數據源中抽取全部數據,再開始處理排序,所有排序完成以後再產生輸出。這樣的過程極大的消耗了內存而且使得整個處理的過程變得緩慢。

相對於這類組件,有一類組件是屬於  Synchronous Transformation 同步轉換,好比:

  • Derived Column
  • Copy Column
  • Data Conversion

這類組件基本上是從數據源一條一條的取,一條一條的處理並同時輸出給下游轉換組件。

因此在上面的幾個示例中,更優的選擇應該是在 OLE DB Source 的操做中使用 SELECT 語句加上排序操做來代替直接使用表或者視圖,這樣避免轉換阻塞。

所以對示例一作出一些修改,去掉中間的排序組件。

 

在 OLE_SRC_Customer 中使用 SELECT 語句加上排序操做使得輸出是已經排好序的結果。

SELECT CustomerID,
       CustomerCompany,
       CustomerName,
       CustomerAddress
FROM dbo.DEMO_MG_Customer
ORDER BY CustomerName

可是再次鏈接到  Merge 組件上時會發生錯誤,由於你還要通知一下 Merge 組件你是如何排序的。

右鍵 OLE_SRC_Customer 選擇 Advanced Editor,在 Input and Output Properties 這裏修改一下 IsSorted 屬性,設置爲 True, 默認是 False。 這樣就告訴了下游轉換組件,這裏的結果是已經排好序的。

同時還須要指定如何排序,按照哪些列來排的序。由於在示例 Merge 中咱們選擇的是 Customer Name, 所以這裏將它的 0 修改成1。 0 表示是不排序的,1 表示是第 一個排序位,這裏應該按照 ORDER BY 後面的列順序來設置,第二個排序列就設置爲 2, 依此類推。

修改完畢後,再運行一下第一個示例,結果是同樣的

這裏的數據量比較少,能夠試一下10W級,100W級 以上使用 Sort 組件和不使用 Sort 組件的差異來體會一下這兩種處理方式的不一樣。

更多 BI 文章請參看 BI 系列隨筆列表 (SSIS, SSRS, SSAS, MDX, SQL Server) 若是以爲這篇文章看了對您有幫助,請幫助推薦,以方便他人在 BIWORK 博客推薦欄中快速看到這些文章。

相關文章
相關標籤/搜索