Gem Ruby ETL 工具漫谈

hooopo for Shopper+ · May 16, 2016 · Last by pengedy replied at July 11, 2016 · 10956 hits
Topic has been selected as the excellent topic by the admin.

activewarehouse-etl

ActiveWarehouse ETL 应该是最早的 Ruby ETL 工具,并且十分强大,支持各种应用场景,但缺点是年久失修,没有再维护。ActiveWarehosue ETl 目标是解决全部 ETL 相关的需求,是一个重量型工具,一般新的 ETL 工具的功能很少是他没有的,但其内部结构十分复杂,并且依赖 ActiveRecord。另外一个缺点是,其支持的 Source 和 Destination 太过老旧,比如,对 Postgresql 不友好。

kiba

Kiba 是 ActiveWarehouse ETL 的维护者新开发的一个 Gem,与 ActiveWarehouse ETL 恰恰相反,Kiba 是一个轻量级的 ETL 工具。目前非常活跃,文档丰富,并且确实很轻,几百行代码勾勒出 ETL 的基本结构。但缺点呢,也很明显,它空无一物,什么都没提供,就是说,如果你的项目想用 Kiba 来解决实际 ELT 问题还差很远,需要自己去实现很多功能,如果不是很熟悉,要踩的坑还很多。另外,Kiba 和 Sidekiq 一样,提供 Kiba Pro,收费版,据说功能很多,支持以下特性:

  • multi-threading (and later, multi-machines) - commonly requested
  • built-in sources/transforms/destinations for common tasks lookups
  • upserts / bulk load modules
  • connectors optimized for parallelism (HTTP pagination extraction)
  • connectors for the cloud (RedShift, ...)
  • built-in helpers for common operations (debugging, limiting, caching...)
  • premium support

ETL

ETL 是 Square 公司开源的一个轻量级的 ETL gem,与 ActiveWarehouse ETL 不同的是,Square ETL 直接操作 SQL,不依赖 ActiveRecord。但可能只是解决 Square 公司的特定问题,目前只支持的是 MySQL Source 和 Destination,并且 Source 和 Destination 必须在同一个 Server 上。另一个致命的缺点是不支持增量更新:

embulk

Embulk 的特点是其丰富的插件和并行处理能力。但其依赖 JRuby 和 Java 让 Ruby 开发者上手很难,并且其体系相当复杂,如果不是数据量巨大就不用考虑了。

kiba-plus

Kiba Plus 是一个基于 Kiba 的增强,包含常用的 Source 和 Destination 实现,例如 MySQL、Postgresql、CSV 等。它具有以下优点:

  • 支持 Postgresql:其实支持 Postgresql 也就意味着很容易支持基于 Pg 的其他数据库,比如 Greenplum、CitusData、Redshift 等。题外话,MySQL 和 Pg 在 OLTP 领域可以说不相上下,但在 OLAP 领域 MySQL 已经被 Pg 甩出一条街了,支持 Pg 意义重大。
  • Fast Load && Insert:由于不依赖 ActiveRecord 和 Sequel 之类 ORM 工具,直接使用 mysql2 和 pg gem 操作 SQL,能够利用更多数据库自身特性,比如 streaming 和 mysql load infile or pg copy 来更快的读取和插入。
  • Incremental Insert:增量更新是 ETL 中不可缺少的部分,如果没有增量更新,即使再快的插入速度和再强的并行处理能力,随着数据量增长,也不可能每次把所以数据都重新插入一遍。

一个从 MySQL 导入到 Pg 的例子:

require 'kiba/plus'

SOURCE_URL = 'mysql://root@localhost/shopperplus'

DEST_URL   = 'postgresql://hooopo@localhost:5432/crm2_dev'

source Kiba::Plus::Source::Mysql, { :connect_url => SOURCE_URL,
                           :query => %Q{SELECT id, email, 'hooopo' AS first_name, 'Wang' AS last_name FROM customers}
                         }

destination Kiba::Plus::Destination::PgBulk2, { :connect_url => DEST_URL,
                                :table_name => "customers",
                                :truncate => true,
                                :columns => [:id, :email, :first_name, :last_name],
                                :incremental => false
                              }

post_process do
  result = PG.connect(DEST_URL).query("SELECT COUNT(*) AS num FROM customers")
  puts "Insert total: #{result.first['num']}"
end

执行:

bundle exec kiba customer_mysql_to_pg.etl

输出:

# I, [2016-05-16T01:53:36.832565 #87909]  INFO -- : TRUNCATE TABLE customers;
# I, [2016-05-16T01:53:36.841770 #87909]  INFO -- : COPY customers (id, email, first_name, last_name) FROM STDIN WITH DELIMITER ',' NULL '\N' CSV
# Insert total: 428972

我们在用这个 forklift 蛮轻量级的,更新也比较频繁

问题来了,为什么用 Ruby 做 ETL?

#1 楼 @vincent 看了一下源码,感觉 forklift 的应用场景更适合 backup tool,作为 datawarehouse 工具太弱了。

比如,只有在 source db 和 destination db 是同一个 db 的时候才是最快的,因为使用了 replace into 语句。其他都情形会 fallback 到单条 insert...

对于 source 和 destination db 不是同一个 db 的情况,其实是没有 bulk load 的,pull 数据使用的是 pagination(limit+offset)方式,似乎不如streaming方式。

#2 楼 @nouse 有什么更好的推荐吗?因为熟悉 Ruby 啊,Ruby 这种脚本语言做 ETL 其实还是挺好用的,处理个百万千万级还是很容易的...

#4 楼 @hooopo 呵呵,问题应该改成为什么要 ETL 了,PostgreSQL 有 fdw,完全不需要。http://blog.taadeem.net/english/2015/03/15/70_Shades_of_Postgres

#5 楼 @nouse 可以理解为 FDW 其实是 ETL 的一种途径,如果你的 Destination 恰好是 Pg,并且你需要整合的资源都有对应的 FDW Wapper,那么 FDW 确实是最简单的方式。

但我觉得像上面图中想用 FDW 替代 ETL 的想法在目前根本行不通,原因是:

A foreign table can be used in queries just like a normal table, but a foreign table has no storage in the PostgreSQL server.

FDW 的数据其实仍然存储在外部服务器,Pg 服务器只存储 schema,并且提供查询接口。而 ETL 是真的把数据搬 Pg 里面。FDW 和 ETL 在这点上的区别就像 View 之于 Materialized View。而 View 虽然和普通表有着相同的接口,但由于数据存储的限制,性能是一个致命问题。同样,FDW 的最大问题也是性能问题。

Citusdata 做过一个测试:

结论是:

the primary benefit of foreign tables is their flexibility. With them, you can issue complex SQL queries on log files, JSON data, or MySQL. In fact, you can even join data from different sources without having to load any of it.

https://www.citusdata.com/blog/50-postgresql-foreign-file-performance

@hooopo ActiveWarehouse ETL 与 activerecord-oracle_enhanced-adapt 好像是同一个作者 rsim?记错了,是 easyBI

9 Floor has deleted

为什么不通过 R 语言解决呢,dateframe 支持内存 join,merge,sample 各个数据源,只要你内存能装下数据就行。

#10 楼 @ericguo 解决的问题不一样。R 是 Data Science 领域的工具,内建丰富的统计分析挖掘相关的库。ETL 是 Data Analysts 领域的一个步骤,把数据从 OLTP 库转换到 OLAP 库,然后进行分析。

正好搜到这个帖子,顺便回复一下。

我在用 Pentaho Kettle 做 ETL,感觉非常好;顺便看到作者写了这么多,也只能对 Ruby ETL 一笑而过了。

#12 楼 @pengedy 可以分享一下哪里好么...

#13 楼 @hooopo

三大特点:同时支持 GUI IDE 和后台任务(方便部署),支持数据库/数据仓库类型丰富,带有报表导出工具。

关键是,我几年前开始用,一直到现在,其实根本没想到会遇见上文提到的大多数问题...

You need to Sign in before reply, if you don't have an account, please Sign up first.