logstash input-jdbc 分页性能优化

场景:

    DB 数据全量同步 Elasticsearch 时,数据量过大时需要使用分页查询。在conf中配置jdbc_paging_enabled、jdbc_page_size这两个参数,input-jdbc插件会自动对SQL进行分页查询,分批同步数据。

问题:

    logstash导入mysql上亿级别数据的效率问题

    项目的ES升级至5.6后,全量数据同步由java定时任务改为logstash。线上数据量比较大,优化索引后单个分页查询执行依旧很慢,需要几十秒。

    原因在于input-jdbc插件的分页是使用临时表分页,每条分页SQL都是将全集查询出来当作临时表,再在临时表上分页查询。这样导致每次分页查询都要对主表进行一次全表扫描。

    举个例子:

    商品表(goods)有1000万条数据,每次同步1万条。input-jdbc插件执行的分页查询sql类似下面这样的。

    select * from (select * from goods left join ...) as T limit 0,10000

解决方案

    通过修改input-jdbc插件源码,支持子查询分页。修改后执行的查询sql类似下面这样的,这样每次分页只需要扫描主表中需要的数量。

select * from (select * from goods limit 0,10000 ) as T left join ...

效果

    项目中单个分页查询都在2S内完成。并且优化后的插件由运维推广到了所有项目,一次有价值的优化。

优化内容:

源码

1、logstash-input-jdbc\lib\logstash\plugin_mixins\jdbc.rb中添加subquery_paging_enabled、sum_statement变量;(具体参见我修改的源码 Line100)

2、perform_query方法中优先判断是否进行子查询优化。(具体参见我修改的源码 Line255)

jdbc.rb源码

配置文件

1、添加两个配置项:

subquery_paging_enabled => "true"

sum_statement => "select count(*) as sum from goods"

2、优化statement SQL

主表改为分页子查询,添加:data_offset、:jdbc_page_size分页参数。例如:

statement => " select * from (select * from goods limit :data_offset , :jdbc_page_size ) as T left join ... "

开发参考

https://github.com/logstash-plugins/logstash-input-jdbc

https://github.com/jeremyevans/sequel

插件构建和安装

1、项目安装依赖(先去github下载源码)

bundle install

2、构建插件gem (在项目主目录下产生logstash-input-jdbc-4.3.5.gem文件)

gem build logstash-input-jdbc.gemspec

3、logstash卸载logstash-input-jdbc插件

/bin/logstash-plugin uninstall logstash-input-jdbc

4、logstash安装本地插件 (先将构建成功的gem文件拷贝至logstash主目录的trade_gem文件夹中)

/bin/logstash-plugin install --no-verify --local ../logstash-input-jdbc-4.3.5.gem

你可能感兴趣的:(logstash input-jdbc 分页性能优化)