在資料倉庫(DW)項目中ETL是必不可缺少的工具。所謂ETL指的是資料抽取(Extract)、轉換(Transform)、清洗(Cleansing)、裝載(Load)。大多數接觸ETL工具設計的人可能覺得轉換(Transform)是設計的重點。在處理轉換(Transform)環節的時候采用局部優化的政策,比如并發線程來提高轉換速度,其實我個人觀點并不贊同,在我接觸過移動倉庫項目中轉換(Transform)通常隻不過是一些substr與trim操作,現在硬體CPU的緩存基本都在2M以上,假設有100個這樣的操作在緩存裡也隻不過才300幾k,而用線程産生的時間片所占的比率則大了幾倍去了。
個人認為ETL重要的環節依次排列下來是:清洗(Cleansing)、裝載(Load)、抽取(Extract)、轉換(Transform).
清洗(Cleansing)是保證資料品質的一個環節。資料品質問題具體表現為正确性、完整性、一緻性、完備性、有效性、時效性和可擷取性等幾個特性。呵呵這是理論叙述說的具體一點就是:
空值處理可捕獲字段空值,進行加載或替換為其他含義資料,并可根據字段空值實作分流加載到不同目标庫。
規範化資料格式 可實作字段格式限制定義,對于資料源中時間、數值、字元等資料,可自定義加載格式。
驗證資料正确性 可利用Lookup及拆分功能進行資料驗證。例如,主叫号861084613409,進行區域碼和電話号碼分解後,可利用Lookup傳回主叫網關或交換機記載的主叫地區,進行資料驗證。
資料替換對于因業務因素,可實作無效資料、缺失資料的替換。
Lookup 查獲丢失資料 Lookup實作子查詢,并傳回用其他手段擷取的缺失字段,保證字段完整性。
這裡先概括的說到這裡。
其實在ETL裡面最讓人頭疼的就是裝載(Load),因為這裡牽扯到一個關鍵的問題就是性能。怎樣讓資料Load的最快才是ETL工具設計成功與否的一個标準。于是我把目前我所知道的資料加載方式做了個測試實驗。下面是測試方式與結果:
測試環境:
OS : Windows XP SP2
DataBase: Mysql 4.1
Program Language:Java (JVM 1.6 b108)
首先我先在Mysql下的Test資料庫中建立了2個表如下:
mysql> show tables;
+----------------+
| Tables_in_test |
| testspeed1 |
| testspeed2 |
2個表的結構都一樣包含3個字段無索引、主鍵。
mysql> desc testspeed;
+--------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
| Filed1 | varchar(20) | YES | | NULL | |
| Filed2 | varchar(20) | YES | | NULL | |
| Filed3 | varchar(20) | YES | | NULL | |
然後寫了一個java程式往testspeed1中插入200w條測試資料:
程式如下:
//通過JDBC批量加載資料
public static void main(String[] args){
......
begin = System.currentTimeMillis();
PreparedStatement stmt = conn.prepareStatement("insert into
TestSpeed" +
"(filed1,filed2,filed3) values (?,?,?)");
for(int i=0;i<2000000;i++)
{
stmt.setString(1,i+"");
stmt.setString(2,i+"");
stmt.setString(3,i+"");
stmt.executeUpdate();
}
end = System.currentTimeMillis();
System.out.println("Cost Time: "+(end - begin) / 1000.0);
}
運作結果 : 372.189 (秒) 約 6分12秒
然後利用mysql将資料直接到出成文本存到D:/Date.txt
mysql> select * into outfile "D:/Date.txt" fields terminated -> by ',' enclosed by
-> '"' lines terminated by '/r/n' from TestSpeed1;
Query OK, 2000000 rows affected (5.59 sec)
約 5.6秒
接着我用JDBC直接讀取資料來比較上面用mysql直接導出的性能差異
Statement stmt = conn.createStatement();
rs = stmt.executeQuery("select * from TestSpeed1;");
while (rs.next()){
}//這裡不做任何操作
運作結果:9.39 秒
再接着我用Mysql的Load Data來與JDBC批量加載資料做比較
這次我将上面導出的資料導回到TestSpeed2中
mysql> LOAD DATA LOCAL INFILE 'D:/Date.txt' INTO
-> TABLE TestSpeed2 FIELDS termina
->ted by ',' enclosed by '"' lines terminated by '/r/n';
Query OK, 2000000 rows affected (7.20 sec)
Records: 2000000 Deleted: 0 Skipped: 0 Warnings: 0
約 7.3 秒
最後将結果總結以下:
操作 Java JDBC mysql
查詢 9.39秒 5.6秒
插入 6分12秒 7.3秒
可見JDBC來操作資料其實并不快,在資料裝載(Load)過程中用資料庫的Load過程可能更好些。