Kettle表輸入表輸出提升50倍的秘訣


這是堅持技術寫作計划(含翻譯)的第26篇,定個小目標999,每周最少2篇。

最近工作需要,需要從Oracle導數據到Mysql,並且需要進行適當的清洗,轉換。
數據量在5億條左右,硬件環境為Winserver 2008R2 64位 ,64G,48核,1T hdd,kettle是8.2,從Oracle(11G,linux服務器,局域網連接)抽到mysql(5.7,本機,win server)。
優化前的速度是讀1000r/s(Oracle)左右,寫1000r/s左右。
優化后的速度是讀8Wr/s(Oracle)左右,寫4Wr/s左右。
因為表的字段大小和類型以及是否有索引都有關系,所以總體來說,提升了20-50倍左右。

mysql 優化

mysql此處只是為了遷移數據用,實際上用csv,或者clickhouse也行。但是擔心csv在處理日期時可能有問題,而clickhouse不能在win下跑,而條件所限,沒有多余的linux資源,而mysql第三方開源框架(不管是導入hdfs),還是作為clickhouse的外表,還是數據展示(supserset,metabase等),還是遷移到tidb,都很方便。所以最終決定用mysql。

Note:此處的mysql只做臨時數據遷移用,所以可以隨便重啟跟修改mysqld參數。如果是跟業務混用時,需要咨詢dba,確保不會影響其他業務。

mysql 安裝及配置優化

  • 從 dev.mysql.com/downloads/m… 下載64位 zip mysql
  • 解壓 mysql-5.7.26-winx64.zip 到目錄,比如 D:\mysql-5.7.26-winx64
  • 創建D:\mysql-5.7.26-winx64\my.ini
[mysqld]
port=3306
basedir=D:\mysql-5.7.26-winx64\
datadir=D:\mysql-5.7.26-winx64\data
net_buffer_length=5242880
max_allowed_packet=104857600
bulk_insert_buffer_size=104857600
max_connections = 1000
innodb_flush_log_at_trx_commit = 2
# 本場景下測試MyISAM比InnoDB 提升1倍左右 default-storage-engine=MyISAM general_log = 1 general_log_file=D:\mysql-5.7.26-winx64\logs\mysql.log innodb_buffer_pool_size = 36G innodb_log_files_in_group=2 innodb_log_file_size = 500M innodb_log_buffer_size = 50M sync_binlog=1 innodb_lock_wait_timeout = 50 innodb_thread_concurrency = 16 key_buffer_size=82M read_buffer_size=64K read_rnd_buffer_size=256K sort_buffer_size=256K myisam_max_sort_file_size=100G myisam_sort_buffer_size=100M transaction_isolation=READ-COMMITTED 復制代碼

Kettle優化

啟動參數優化

本機內存較大,為了防止OOM,所以調大內存參數,創建環境變量 PENTAHO_DI_JAVA_OPTIONS = -Xms20480m -Xmx30720m -XX:MaxPermSize=1024m 起始20G,最大30G

表輸入和表輸出開啟多線程

表輸入如果開啟多線程的話,會導致數據重復。比如 select * from test ,起3個線程,就會查3遍,最后的數據就是3份。肯定不行,沒達到優化的目的。
因為source是oracle,利用oracle的特性: rownum 和函數: mod ,以及kettle的參數: Internal.Step.Unique.Count,Internal.Step.Unique.Number

select * from (SELECT test.*,rownum rn FROM test ) where mod(rn,${Internal.Step.Unique.Count}) = ${Internal.Step.Unique.Number} 復制代碼

解釋一下

  • rownum 是oracle系統順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,意味着,如果排序字段或者數據有變化的話,rownum也會變(也就是跟物理數據沒有對應關系,如果要對應關系的話,應該用rowid,但是rowid不是數字,而是類似 AAAR3sAAEAAAACXAAA  的編碼),所以需要對rownum進行固化,所以將 SELECT test.*,rownum rn FROM test 作為子查詢
  • mod 是oracle的取模運算函數,比如, mod(5,3)  意即 5%3=2 ,就是 5/3=1...2 中的2,也就是如果能獲取到總線程數,以及當前線程數,取模,就可以對結果集進行拆分了。 mod(行號,總線程數)=當前線程序號
  • kettle 內置函數 ${Internal.Step.Unique.Count} 和 ${Internal.Step.Unique.Number} 分別代表線程總數和當前線程序號

而表輸出就無所謂了,開多少線程,kettle都會求總數然后平攤的。

image.png
右鍵選擇表輸入或者表輸出,選擇 改變開始復制的數量... 注意,不是一味的調大就一定能提升效率,要進行測試的。
表輸入時,注意勾選替換變量
image.png
image.png
  • 修改提交數量(默認100,但是不是越大越好)
  • 去掉裁剪表,因為是多線程,你肯定不希望,A線程剛插入的,B給刪掉。
  • 必須要指定數據庫字段,因為表輸入的時候,會多一個行號字段。會導致插入失敗。當然如果你在創建表時,多加了行號字段,當做自增id的話,那就不需要這一步了。
  • 開啟批量插入
image.png

Note: 通過開啟多線程,速度能提升5倍以上。

開啟線程池及優化jdbc參數

image.png
image.png
image.png

運行觀察結果

image.png
注意調整不同的參數(線程數,提交數),觀察速度。

其余提升空間

  1. 換ssd
  2. 繼續優化mysql參數
  3. 換引擎,比如,tokudb
  4. 換抽取工具,比如streamsets,datax
  5. 換數據庫,比如 clickhouse,tidb,Cassandra
  6. kettle集群
characterEncoding GBK
rewriteBatchedStatements true
useServerPrepStmts false
useCompression  true

作者:趙安家
鏈接:https://juejin.im/post/5d0087f9f265da1bd6059cc1
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM