最近在使用 flink sql (jdbc)执行一个简单表同步,可是执行了半天都没有执行完,后面通过 jstack 找到了问题原因:where条件没有下推到数据库执行。
任务如下:
create table mysql_a (
id1 string,
id2 atring,
...
primary key(id1) not enforced
) with (
'connector' = 'jdbc',
'url' = 'jdbc:mysql://${mysql_hosts}:${mysql_port}/test',
'username' = '${mysql_username}',
'password' = '${mysql_pass}',
'scan.fetch-size'='1000',
'table-name' = 'a'
);
create table es_sitrdw001_di_risk (
id1 string,
id2 atring,
...
primary key(id1) not enforced
) with (
'connector' = '${es_connector}',
'hosts' = '${es_hosts}',
'username' = '${es_username}',
'password' = '${es_pass}',
'sink.bulk-flush.max-actions' = '1000',
'sink.bulk-flush.interval' = '1s',
'index' = 'aa'
);
insert into es_a
select *
from mysql_a
where id1 = '123456'
;
简单来说,就是把 a表某条数据 同步到 es 相应索引下。其中 id1 加了索引,a表数据 200万条,150+字段,同步一次需要执行30分钟+
按道理来说,只有一条数据,不应该执行这么慢呀。下面记录了本人排查过程。
1、使用 jstack 打印线程日志
为了了解 flink 到底卡在哪个步骤,在程序执行5分钟后,在服务器上(或者本地开发环境)执行 jps命令
找到 flink 执行的线程 id。
接下来执行 jstack -l 15044 > /tmp/flink_jstack.log
将线程日志打印下来。
打开查看线程栈日志,我们可以看到程序卡在了 org.apache.flink.connector.jdbc.table.JdbcRowDataInputFormat.open() 这里
2、打断点
在org.apache.flink.connector.jdbc.table.JdbcRowDataInputFormat.open() 方法里面打断点
resultSet = statement.executeQuery();
这里是去数据库执行 SQL,将 originalSql 打印出来。发现where 条件没有了,查询 sql 只有 select id1,id1 … from a;
好家伙,全量查询,然后在内存里过滤数据,难怪执行特别慢!!!
至此问题原因找到了。
总结一下
本文主要介绍了 如何利用 jstack 定位问题,并通过断点了解到具体执行慢的原因,重在排查问题的技巧和思路,希望对你有帮助。
下篇继续介绍 flink jdbc 源码,解释为什么where 条件没有了,感兴趣的伙伴可以去找找哈。
《flink sql 源码走读 — 解释flink jdbc where 条件为什么没有下推数据库》
flink sql (jdbc)如何支持where 条件下推数据库