數(shù)據(jù)處理利器-SSIS入門與進(jìn)階
2010-06-29 14:42 靈感之源 閱讀(79385) 評(píng)論(23) 收藏 舉報(bào)
使用SSIS,首先是因?yàn)楣ぷ餍枰浯?,在澳洲找工作?個(gè)星期里,我發(fā)現(xiàn)招聘需求中有太多技術(shù)我沒有掌握了,其實(shí)這些技術(shù),只需要幾天就可以入門,幾個(gè)星期就可以進(jìn)階,為什么不花一點(diǎn)時(shí)間去掌握一門新的技術(shù)呢?多一門技術(shù)與少一門差異是很大的,招聘需求往往會(huì)寫明必須掌握的技術(shù),你缺一門,你就不好意思打招呼了。
SSIS是從MS SQL 2005開始引入的,實(shí)際上是DTS的馬甲,是SQL Server Integration Service的縮寫。DTS也好,SSIS也罷,都是ETL(Extract Transform Load)工具,一般用來導(dǎo)入數(shù)據(jù)到數(shù)據(jù)庫。SSIS比普通的ETL更進(jìn)一步,它是可視化的,用Visual Studio來開發(fā),包文件(*.dtsx)采用的是XML格式。跟Office2007+系列文檔擴(kuò)展名一樣,都是???x,代表xml格式,但他沒有壓縮成zip文件罷了。
我在新格式的工作內(nèi)容是研究SSIS的性能。公司是做能源管理的,每隔一段時(shí)間(如15分鐘)需要從測(cè)量表中提取數(shù)據(jù),不斷積累后,一個(gè)測(cè)量表5年的數(shù)據(jù)有231MB,134萬條。目前每天要處理6500多個(gè)文件,現(xiàn)有活動(dòng)數(shù)據(jù)是3億條記錄。

注意:因?yàn)橐泼竦搅税闹尴つ幔到y(tǒng)和開發(fā)環(huán)境全部是英文,我也不知道中文對(duì)應(yīng)是什么,所以以下說明全部使用英文,并加上我猜想的中文。
首先使用SSIS創(chuàng)建一個(gè)簡單的Integration Services Project: File->New->Project->Business Intellegence Projects->Integration Services Project
(新建項(xiàng)目1)
(新建項(xiàng)目2)
添加一個(gè)Foreach Loop Container
, 雙擊這個(gè)Foreach Loop Container,點(diǎn)擊左邊的Collection,選擇來源文件目錄(Folder),輸入文件類型(Files)。
點(diǎn)擊Variable Mappings,點(diǎn)擊New Variable,在Name輸入變量名稱。這個(gè)變量是目錄循環(huán)中每個(gè)文件的值,稍后會(huì)用在每個(gè)文件的處理中。
再在里面添加一個(gè)Data Flow Task
,雙擊這個(gè)Data Flow Task,進(jìn)入了Data Flow標(biāo)簽(Control Flow右邊)。因?yàn)樵嘉募菑臏y(cè)量表讀取出來然后寫到CSV文件的,所以我們使用Flat File Source(就是文本文件,CSV文件也屬于這類)。
雙擊Flat File Source,F(xiàn)lat File connection manager,點(diǎn)右邊的New新建一個(gè)文本文件連接,給連接一個(gè)名字,選擇一個(gè)例子文件,按照你的情況輸入header rows to skip(跳過頭列),如果第一列是列名稱,你應(yīng)該輸入1。
點(diǎn)擊Advanced(高級(jí)),給每列選擇正確的數(shù)據(jù)類型,確定。
點(diǎn)擊Columns(列),給每列起個(gè)名字。
在我們的數(shù)據(jù)中,都是基本的設(shè)備、日期、溫度、濕度、氣壓等等。但某些記錄是錯(cuò)誤的(譬如沒有日期),這些記錄就要忽略,日期是細(xì)分為:年、月、日、小時(shí)、分鐘的,必須合并,還有溫度、濕度某些情況是沒有的,你就要處理為NULL。
對(duì)于錯(cuò)誤的記錄(日期為空),我們要添加一個(gè)Conditional Split,在Condition(條件)中輸入 “LEN(TRIM(Year)) > 0”(只需要判斷年是否為空)。
關(guān)于表達(dá)式,需要特別說明一下:你可以選作左邊的變量或者列,或者右邊的各種內(nèi)置函數(shù)。你只需要直接拖放變量、列或者函數(shù)到輸入框便可。
對(duì)于完整的日期,我們需要添加一個(gè)Derived Column(派生列),從Conditional Split拖放關(guān)系,要求你選擇跳轉(zhuǎn)到指定流程的條件。
雙擊該派生列,在Expression(表達(dá)式)中輸入“Year + "-" + Month + "- " + Day + " " + Hour + ":" + Minute + ":00"”(構(gòu)造標(biāo)準(zhǔn)的日期格式,如:2010-06-29 16:11),日期類型選database timestamp(根據(jù)你自己的實(shí)際情況吧)。
對(duì)于NULL數(shù)值類型,你也需要添加一個(gè)派生列,然后在表達(dá)式中輸入LEN(TRIM(Temperature)) > 0 ? (DT_R8)Temperature : NULL(DT_R8)。這里用DT_R8是因?yàn)闇囟仁莇ouble。
然后添加一個(gè)導(dǎo)入目標(biāo),我們的目的是把數(shù)據(jù)導(dǎo)入到MS SQL Server,所以添加一個(gè)SQL Server Destination,雙擊進(jìn)入編輯
點(diǎn)擊New新建一個(gè)數(shù)據(jù)庫連接。
點(diǎn)擊Mapping(映射),把CSV文件的列對(duì)應(yīng)到數(shù)據(jù)庫表
接下來就是運(yùn)行了,如果你正確設(shè)置,數(shù)據(jù)自然會(huì)導(dǎo)入到數(shù)據(jù)庫。
這里需要注意,SSIS的設(shè)計(jì)有頗多的bug,譬如下面提及的腳本編譯問題,還有在設(shè)計(jì)器中,不能通過編輯目標(biāo)數(shù)據(jù)來直接編輯連接,你要雙擊下方的控件列表。另外,當(dāng)你編輯連接,你會(huì)發(fā)現(xiàn)之前選擇的例子文件會(huì)丟失,每次你都必須重新選擇。
如果要發(fā)布到SQL Server,你要修改SSIS的項(xiàng)目屬性:Project->(your project name) Properties->Deployment Utility->CreateDeploymentUtility->True。然后雙擊bin\Deployment下面的Deployment文件,按照提示一步步Next便可(建議安裝到MS SQL Server,而不是文件系統(tǒng))。如果要查看已經(jīng)安裝的,打開SQl Server Management Studio,選擇Integration Services,打開。
在開發(fā)SSIS的過程中,你可能會(huì)遇到一些詭異的情況。譬如:
1.類型轉(zhuǎn)換,你在Prorgress(進(jìn)度)標(biāo)簽中可以查看詳細(xì)的結(jié)果,但往往結(jié)果都比較含糊。一般都是類型沒有選對(duì),譬如SSIS會(huì)自動(dòng)選回字符串類型,你又要手工改回database timestamp
2.目標(biāo)數(shù)據(jù)庫中的數(shù)據(jù)表字段變化了,或者來源文件格式變了,你運(yùn)行,肯定錯(cuò)誤,但在Progress(進(jìn)度)中,你難以看出個(gè)門道。一般看見設(shè)計(jì)圖中的出現(xiàn)警告或者錯(cuò)誤小圖標(biāo),你鼠標(biāo)挪上去停一下,就會(huì)給個(gè)模糊的提示,雙擊,會(huì)提示你修正。
一些特別情況:
1.內(nèi)置的控件無法滿足需要,怎么辦?自己寫控件:陳希章同學(xué)寫的為SSIS編寫自定義任務(wù)項(xiàng)(Task)之入門篇 。這里還有另外一個(gè)例子:執(zhí)行SQL Job并等待其結(jié)束。
2.需要復(fù)雜的處理:在Control Flow中用Script Task,在Data Flow中用Script Component;
關(guān)于腳本:添加一個(gè)Script Task,雙擊,點(diǎn)擊Script(腳本),如果你是SQL 2005 SP1或以下,你就必須選PrecompileScriptIntoBinaryCode,否則你將無法正確運(yùn)行?;蛘吣憬o2005安裝SP2;
3.你需要讓SSIS執(zhí)行并盡量等待你去做其他事情(矛盾啊。。。),你可以添加一個(gè)Script Task,輸入System.Threading.Thread.Sleep(想多長就多長);
關(guān)于變量:你需要注意變量的作用域。一般的作用域是Package(包)。在腳本中,如果你想訪問變量,你就必須在ReadOnlyVariables(只讀變量)和ReadWriteVariables(可讀寫變量)中輸入變量名稱(多個(gè)變量用逗號(hào)分隔)。然后在編輯腳本代碼中,使用Dts.Variables("YourVariableName")來訪問變量。
關(guān)于郵件發(fā)送,如果使用內(nèi)置的Send Mail Task,你會(huì)發(fā)現(xiàn)無法指定登陸用戶名和密碼。我改用腳本調(diào)用sourceforge上opensmtp,或者,你可以使用MS SQL Server自帶的郵件功能,然后用SQL Excute Task執(zhí)行,譬如:
exec msdb.dbo.sp_send_dbmail @profile_name = 'Foo',
@recipients = 'FooReceiver',
@subject = 'FooSubject',
@body = 'FooBody'
@body_format = 'Text'
稍后我會(huì)給出使用最老套的c#代碼導(dǎo)入數(shù)據(jù)方式(包括多線程方式等多種方式),和SSIS比較性能,因?yàn)槲矣X得寫c#代碼怎么也不能輸給SSIS這種重量級(jí)的工具啊,所以我卷起袖子就大干一場(chǎng),寫了多種方式,但結(jié)果很特別。。。。。。
浙公網(wǎng)安備 33010602011771號(hào)