You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch提交SQL与源码不符,Postgres执行计划异常求因

问题排查:Spring Batch SQL被改写导致Postgres性能劣化

正在排查基于Spring Boot、Spring Batch 4.2.0和Postgres 14.5的应用性能问题时,发现异常情况:Postgres端执行的SQL查询与Spring Batch源码(JdbcStepExecutionDao.java)中的查询存在差异——子查询中多了外层表的JE.前缀,这导致Postgres生成的执行计划包含两次全表扫描(FTS),性能较差;而源码中的查询执行计划使用索引扫描,性能更优。现疑问:该SQL改写是由Postgres服务端、JDBC驱动还是其他中间层导致的?


一、Postgres端实际执行的SQL及执行计划

执行SQL

SELECT  SE.STEP_EXECUTION_ID, SE.STEP_NAME, SE.START_TIME, SE.END_TIME, SE.STATUS, SE.COMMIT_COUNT, SE.READ_COUNT, SE.FILTER_COUNT, SE.WRITE_COUNT, 
                SE.EXIT_CODE, SE.EXIT_MESSAGE, SE.READ_SKIP_COUNT, SE.WRITE_SKIP_COUNT, SE.PROCESS_SKIP_COUNT, SE.ROLLBACK_COUNT, SE.LAST_UPDATED, SE.VERSION, 
                JE.JOB_EXECUTION_ID, JE.START_TIME, JE.END_TIME, JE.STATUS, JE.EXIT_CODE, JE.EXIT_MESSAGE, JE.CREATE_TIME, JE.LAST_UPDATED, JE.VERSION 
  from N_BATCH_JOB_EXECUTION JE, N_BATCH_STEP_EXECUTION SE 
  where       
       SE.JOB_EXECUTION_ID in 
                     (SELECT JOB_EXECUTION_ID 
                        from N_BATCH_JOB_EXECUTION 
                       where JE.JOB_INSTANCE_ID = $1)     
   and SE.JOB_EXECUTION_ID = JE.JOB_EXECUTION_ID       
   and SE.STEP_NAME = $2 
   order by SE.START_TIME desc, SE.STEP_EXECUTION_ID desc

执行计划

Sort  (cost=154.08..154.11 rows=13 width=217)
  Sort Key: se.start_time DESC, se.step_execution_id DESC
  ->  Hash Join  (cost=69.71..153.83 rows=13 width=217)
        Hash Cond: (se.job_execution_id = je.job_execution_id)
        Join Filter: (SubPlan 1)
        ->  Bitmap Heap Scan on n_batch_step_execution se  (cost=4.49..88.54 rows=26 width=156)
              Recheck Cond: ((step_name)::text = 'notf0270f8e50fd95b44da8b34cb1ea829cc74'::text)
              ->  Bitmap Index Scan on n_batch_step_exec_step_name_job_exec_id_idx  (cost=0.00..4.48 rows=26 width=0)
                    Index Cond: ((step_name)::text = 'notf0270f8e50fd95b44da8b34cb1ea829cc74'::text)
        ->  Hash  (cost=45.10..45.10 rows=1610 width=77)
              ->  Seq Scan on n_batch_job_execution je  (cost=0.00..45.10 rows=1610 width=77)
        SubPlan 1
          ->  Result  (cost=0.00..45.10 rows=1610 width=8)
                One-Time Filter: (je.job_instance_id = 1)
                ->  Seq Scan on n_batch_job_execution  (cost=0.00..45.10 rows=1610 width=8)

二、Spring Batch源码中的SQL及执行计划

源码SQL片段

where       
       SE.JOB_EXECUTION_ID in 
                     (SELECT JOB_EXECUTION_ID 
                        from N_BATCH_JOB_EXECUTION 
                       where JOB_INSTANCE_ID = $1) 

对应执行计划

Sort  (cost=17.74..17.75 rows=1 width=217)
  Sort Key: se.start_time DESC, se.step_execution_id DESC
  ->  Nested Loop  (cost=0.59..17.73 rows=1 width=217)
        ->  Nested Loop  (cost=0.30..16.35 rows=1 width=77)
              ->  Index Scan using n_batch_job_execution_job_instance_id_idx on n_batch_job_execution  (cost=0.15..8.17 rows=1 width=8)
                    Index Cond: (job_instance_id = 1)
              ->  Index Scan using n_batch_job_execution_pkey on n_batch_job_execution je  (cost=0.15..8.17 rows=1 width=69)
                    Index Cond: (job_execution_id = n_batch_job_execution.job_execution_id)
        ->  Index Scan using n_batch_step_exe_idx on n_batch_step_execution se  (cost=0.29..1.37 rows=1 width=156)
              Index Cond: (job_execution_id = je.job_execution_id)
              Filter: ((step_name)::text = 'notf0270f8e50fd95b44da8b34cb1ea829cc74'::text)

三、改写原因分析

  1. 排除Postgres服务端:Postgres只会对传入的SQL做查询优化(如谓词下推、连接顺序调整),但不会主动将非关联子查询改写成关联子查询(即不会给子查询的条件添加外层表别名)。执行计划中的全表扫描是因为关联子查询的特性导致无法优化,而非服务端改写SQL。

  2. 排除JDBC驱动:Postgres JDBC驱动默认仅负责SQL的传输、参数绑定和结果解析,没有改写SQL结构的逻辑。除非配置了特殊的批量插入类参数,但这类参数不会修改查询的关联逻辑。

  3. 最可能的来源:应用侧中间组件

    • SQL拦截器/监控组件:应用中如果集成了性能监控、SQL审计类组件(如链路追踪框架、自定义AOP切面),可能会在SQL执行前做改写,误将外层表别名引入子查询。
    • 动态SQL生成bug:如果应用通过ORM框架或自定义动态SQL逻辑拼接查询,可能在拼接过程中错误地将外层表的别名带入子查询条件。
    • Spring Batch扩展改写:若项目对Spring Batch的JdbcStepExecutionDao做了自定义扩展,可能在重写SQL时引入了错误。

总结:SQL的改写大概率来自应用侧的中间组件,建议排查应用中的SQL拦截逻辑、动态SQL生成代码或Spring Batch的自定义扩展。

内容的提问来源于stack exchange,提问作者tavi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 18:07:20