Apache NiFi ExecuteSQLRecord性能瓶颈排查及技术问询
针对NiFi ExecuteSQLRecord与MSSQL性能问题的解答
1. 单CPU下NiFi的该性能表现是否正常?
这个表现是正常的。原因在于:
- MSSMS是MSSQL的原生客户端,直接和数据库交互,只处理查询结果的展示,没有额外中间层开销;而NiFi的
ExecuteSQLRecord是通过JDBC驱动封装的处理器,除了执行查询,还要完成结果集转Record对象、序列化(转CSV)、写入内容仓库等一系列串行操作,这些都会增加整体耗时。 - 你提到吞吐量随线程数线性增长,说明单线程下的瓶颈确实在NiFi的本地处理环节,而非网络或数据库,这也符合单线程串行处理的性能特征。所以单CPU下40秒的耗时对比内网查询的18秒,是合理的差异。
2. 22秒用于数据拉取及存储至内容仓库是否合理?
这个耗时是合理的。咱们来拆解一下:
- 数据库内网查询的18秒是纯数据库计算+网络传输到客户端的时间,而NiFi的22秒额外耗时包含了:JDBC结果集的遍历与解析、100万行数据的Record对象创建、CSV格式序列化、内容仓库的磁盘写入(哪怕是高级SSD,单线程下文件创建、数据写入、刷盘都有一定开销)。
- 100万行转成60MB的CSV文件,单线程下完成这些操作需要的时间基本在这个区间内,如果你的内容仓库是磁盘存储而非内存,这个耗时完全符合预期。
3. NiFi从MSSQL拉取数据是否为拉取模式,是否存在过多往返?
NiFi是拉取模式,但如果配置不当确实会存在过多往返:
ExecuteSQLRecord基于JDBC驱动拉取数据,MSSQL JDBC驱动默认的fetch size是10,也就是说每次只从数据库拉取10行数据,100万行就会产生10万次往返请求,这会大幅增加耗时。- 不过你提到已经排除了网络瓶颈,推测可能已经调整过
fetch size属性,但还是建议检查该处理器的Fetch Size配置,设置为较大的值(比如10000),可以减少往返次数,进一步优化拉取耗时。
4. 如何统计结果集转CSV及写入内容仓库的耗时?
可以通过拆分NiFi的处理流程,结合属性埋点来精准统计:
- 步骤1:拆分处理环节:把
ExecuteSQLRecord的职责拆分,让它只负责执行查询并输出Record格式的数据,然后用单独的ConvertRecord处理器完成CSV转换,最后用PutFile(或依赖内容仓库存储)完成写入。 - 步骤2:添加时间戳属性:
- 在
ExecuteSQLRecord之后添加UpdateAttribute,新增属性record_start = ${now()} - 在
ConvertRecord之后添加UpdateAttribute,新增属性convert_end = ${now()} - 在写入环节之后添加
UpdateAttribute,新增属性write_end = ${now()}
- 在
- 步骤3:计算时间差:使用NiFi的属性表达式计算各环节耗时,比如:
- 转换耗时:
${convert_end:minus(${record_start}):toNumber()}(单位毫秒) - 写入耗时:
${write_end:minus(${convert_end}):toNumber()}
- 转换耗时:
- 另外,也可以查看NiFi的Provenance数据,每个处理器的处理时长会被记录,但拆分流程的方式能更精准地区分转换和写入的耗时。
内容的提问来源于stack exchange,提问作者VB_
相关产品推荐
相关产品推荐

