向量化引擎 IF 函数缺失短路求值导致 from_unixtime 异常及性能担忧 、兼容性问题

Viewed 20

SQL

select
        o.plat_order_id,
     o.pay_stamp,o.id,
      if(pay_stamp >= 30,from_unixtime(pay_stamp-29),'')
        from hexin_ods.ods_erp_oms_tiktok_order o
where o.id >10000

异常

[HY000][1105] Exception, msg: (172.16.0.26)[INVALID_ARGUMENT]Operation from_unixtime_new of -29, yyyy-MM-dd HH:mm:ss is invalid

image.png

验证及猜测

from_unixtime(if(...))成功if(..., from_unixtime(...)) 失败,这直接证明了问题的核心在于 表达式求值顺序(Evaluation Order) 和 向量化引擎的参数预先计算机制。

在 Doris 4.0 的向量化引擎中,IF 函数不再像传统行式引擎那样支持“短路求值”,而是采用“全量求值后选择”的策略。

EXPLAIN

  • if(..., from_unixtime(...))
PLAN FRAGMENT 0
  OUTPUT EXPRS:
    plat_order_id[#75]
    pay_stamp[#76]
    id[#77]
"    if(pay_stamp >= 30,from_unixtime(pay_stamp-29),'')[#78]"
  PARTITION: HASH_PARTITIONED: id[#0]
""
  HAS_COLO_PLAN_NODE: false
""
  VRESULT SINK
     MYSQL_PROTOCOL
""
  0:VOlapScanNode(111)
"     TABLE: hexin_ods.ods_erp_oms_tiktok_order(ods_erp_oms_tiktok_order), PREAGGREGATION: ON"
     PREDICATES: ((id[#0] > 10000) AND (__DORIS_DELETE_SIGN__[#73] = 0))
     partitions=1/1 (ods_erp_oms_tiktok_order)
"     tablets=10/10, tabletList=1771689840857,1771689840859,1771689840861 ..."
"     cardinality=5998695, avgRowSize=374.03387, numNodes=2"
     pushAggOp=NONE
"     final projections: plat_order_id[#4], pay_stamp[#60], id[#0], if((pay_stamp[#60] >= 30), from_unixtime((pay_stamp[#60] - 29)), '')"
     final project output tuple id: 1
""
""
""
========== STATISTICS ==========
planned with unknown column statistics

  • from_unixtime(if(...))
PLAN FRAGMENT 0
  OUTPUT EXPRS:
    plat_order_id[#75]
    pay_stamp[#76]
    id[#77]
"    from_unixtime(if(pay_stamp >= 30,pay_stamp-29,0))[#78]"
  PARTITION: HASH_PARTITIONED: id[#0]
""
  HAS_COLO_PLAN_NODE: false
""
  VRESULT SINK
     MYSQL_PROTOCOL
""
  0:VOlapScanNode(111)
"     TABLE: hexin_ods.ods_erp_oms_tiktok_order(ods_erp_oms_tiktok_order), PREAGGREGATION: ON"
     PREDICATES: ((id[#0] > 10000) AND (__DORIS_DELETE_SIGN__[#73] = 0))
     partitions=1/1 (ods_erp_oms_tiktok_order)
"     tablets=10/10, tabletList=1771689840857,1771689840859,1771689840861 ..."
"     cardinality=5999294, avgRowSize=373.90082, numNodes=2"
     pushAggOp=NONE
"     final projections: plat_order_id[#4], pay_stamp[#60], id[#0], from_unixtime(if((pay_stamp[#60] >= 30), (pay_stamp[#60] - 29), 0))"
     final project output tuple id: 1
""
""
""
========== STATISTICS ==========
planned with unknown column statistics

关于向量化引擎 IF 函数求值顺序的疑问

我们在使用 Doris 4.0.3 向量化引擎时发现一个问题:IF(condition, expr_true, expr_false)预先计算所有分支的参数,然后再根据条件选择结果。这导致:

  1. SQL 行为变更:3.12 版本能正常运行的 SQL(用 IF 保护函数参数)在 4.x 版本报错
  2. 潜在性能损耗:即使某行数据不满足条件,其对应的分支表达式仍会被计算

想请教几个问题:

Q1: 这是长期设计策略吗?
向量化引擎是否计划一直采用"全量求值"而非"短路求值"?

Q2: 设计目的是什么?

  • 是为了 SIMD 批量处理效率?
  • 还是为了简化执行器逻辑?
  • 是否有相关的设计文档可以参考?

Q3: 性能影响有评估吗?
当 IF 条件过滤掉 50% 或 90% 的数据时,额外计算那些"最终不会使用"的分支,会带来多少 CPU 开销?是否有 benchmark 数据?

Q4: 是否有优化计划?

  • 是否考虑对昂贵函数(如 UDF、正则、日期转换)实现懒加载/短路优化?
  • 是否考虑让 from_unixtime() 等函数对非法参数返回 NULL 而非抛异常?

我们的担忧

场景 行式引擎 向量化引擎 影响
IF 保护函数参数 ✅ 有效 ❌ 无效 SQL 需重写
过滤 90% 数据 只算 10% 100% 都算 可能浪费 90% 计算
非法参数处理 返回 NULL 抛异常 查询稳定性下降

希望社区能帮忙澄清一下设计意图,方便我们评估是否升级以及如何优化 SQL。谢谢!

0 Answers