hive udf 执行一次调用多次问题

sql 复制代码
SELECT AppMktApi(
      'http://xx.xx.xx.xx:8282/uph/sou',
      'POST',
      concat('{','"topicId": "', 'RZRQ', '",','"auditorId": "','ngw', '",','"channels": "', 'ol', '",','"content": "', '融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注', '",','"destIds": ', '[11500435,11500433,11304133,11000126,11000619,11504802]', ',','"destType": "', '1', '",','"priority": "', '5','",','"providerId": "','ngw', '",','"rTopic": "', 'Push_Result','",','"ack": "','1','"}'),
    -- '{"topicId":"RZRQ","auditorId":"ngw","channels":"ol","content":"融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注","destIds":[11500435,11500433,11304133,11000126,11000619,11504802],"destType":"1","priority":"5","providerId":"ngw","rTopic":"Push_Result","ack":"1"}',
      'Content-Type: application/json'
    ) AS result

执行一次调用了两次,查看执行计划

sql 复制代码
explain extended SELECT AppMktApi(
      'http://xx.xx.xx.xx:8282/uph/sou',
      'POST',
        '{\"topicId\":\"RZRQ\",\"auditorId\":\"ngw\",\"channels\":\"ol\",\"content\":\"融资融券业务指标变动提醒\",\"longtext\":\"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注\",\"destIds\":[11500435,11500433,11304133,11000126,11000619,11504802],\"destType\":\"1\",\"priority\":\"5\",\"providerId\":\"ngw\",\"rTopic\":\"Push_Result\",\"ack\":\"1\"}',
      'Content-Type: application/json'
    ) AS result

结果显示

sql 复制代码
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Fetch Operator
limit: -1
Processor Tree:
TableScan
alias: _dummy_table
Row Limit Per Split: 1
GatherStats: false
Select Operator
expressions: '{"response":"{\"errcode\":\"0\",\"msgId\":\"2025090239116000001\"}","curlCommand":"curl -X POST -H \"Content-Type: application/json\" -d '{\"topicId\":\"RZRQ\",\"auditorId\":\"ngw\",\"channels\":\"ol\",\"content\":\"融资融券业务指标变动提醒\",\"longtext\":\"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注\",\"destIds\":[11500435,11500433,11304133,11000126,11000619,11504802],\"destType\":\"1\",\"priority\":\"5\",\"providerId\":\"ngw\",\"rTopic\":\"Push_Result\",\"ack\":\"1\"}' http://xx.xx.xx.xx:8282/uph/sou"}' (type: string)
outputColumnNames: _col0
ListSink

执行计划里仅显示 Stage-0 (属于客户端本地阶段,无分布式计算),且扫描的是 dummy_table (Hive 虚拟表,仅用于返回固定值,无需 MapReduce 处理 )。

原因:

  1. Hive 执行计划的"预执行 + 实际执行"

Hive 在解析含 UDF(这里 AppMktApi; 可理解为自定义函数逻辑)的查询时,可能会先做语法/类型校验,执行计划中的 (type: string),触发一次接口调用;实际执行查询(扫描 _dummy_table; 后处理数据)时,再触发一次。尤其当 UDF 里有固定参数拼接(像你 SQL 里构造固定请求体),Hive 校验阶段可能会提前执行 UDF 逻辑,导致额外调用。

2 解决方案

方案 1:避免 UDF 在校验阶段执行

Hive 校验阶段会执行 UDF(因固定参数/语法验证),可通过延迟 UDF 逻辑执行规避:

方法:参数化请求体(从固定值改为表字段)

把 UDF 里固定拼接的请求体,改成从表中读取字段动态生成。这样 Hive 校验阶段无实际参数,不会触发接口调用。

示例改造:

原 SQL(固定请求体,触发校验调用):

sql 复制代码
SELECT AppMktApi(
      'http://xx.xx.xx.xx:8282/uph/sou',
      'POST',
      concat('{','"topicId": "', 'RZRQ', '",','"auditorId": "','ngw', '",','"channels": "', 'ol', '",','"content": "', '融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注', '",','"destIds": ', '[11500435,11500433,11304133,11000126,11000619,11504802]', ',','"destType": "', '1', '",','"priority": "', '5','",','"providerId": "','ngw', '",','"rTopic": "', 'Push_Result','",','"ack": "','1','"}'),
    -- '{"topicId":"RZRQ","auditorId":"ngw","channels":"ol","content":"融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注","destIds":[11500435,11500433,11304133,11000126,11000619,11504802],"destType":"1","priority":"5","providerId":"ngw","rTopic":"Push_Result","ack":"1"}',
      'Content-Type: application/json'
    ) AS result

改造后(请求体存表,动态读取):

  1. 建辅助表存请求体(一次插入,复用):
sql 复制代码
create table tmp.request_body(
name string
)

insert into table tmp.request_body 
select '{"topicId": "RZRQ","auditorId": "ngw","channels": "ol","content": "融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注","destIds": [11500435,11500433,11304133,11000126,11000619,11504802],"destType": "1","priority": "5","providerId": "ngw","rTopic": "Push_Result","ack": "1"}
' as name;
  1. 关联查询动态传参(Hive 校验阶段仅解析逻辑,不执行 UDF):
sql 复制代码
SELECT AppMktApi(
      'http://xx.xx.xx.xx:8282/uph/sou',
      'POST',
    --   concat('{','"topicId": "', 'RZRQ', '",','"auditorId": "','ngw', '",','"channels": "', 'ol', '",','"content": "', '融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注', '",','"destIds": ', '[11500435,11500433,11304133,11000126,11000619,11504802]', ',','"destType": "', '1', '",','"priority": "', '5','",','"providerId": "','ngw', '",','"rTopic": "', 'Push_Result','",','"ack": "','1','"}'),
    -- '{"topicId":"RZRQ","auditorId":"ngw","channels":"ol","content":"融资融券业务指标变动提醒","longtext":"尊敬的投资者您好!您信用账户持有的科泰电源(300153)折算率已调整,敬请关注","destIds":[11500435,11500433,11304133,11000126,11000619,11504802],"destType":"1","priority":"5","providerId":"ngw","rTopic":"Push_Result","ack":"1"}',
    name,
      'Content-Type: application/json'
    ) AS resul from tmp.request_body 

原理:Hive 校验阶段仅检查表字段引用,不会实际执行 AppMktApi ,仅实际执行阶段(扫描表时)触发 1 次调用。

相关推荐
juniperhan16 小时前
Flink 系列第4篇:Flink 时间系统与 Timer 定时器实战精讲
java·大数据·数据仓库·flink
juniperhan19 小时前
link 系列第7篇:Flink 状态管理全解析(原理+类型+存储+实操)
大数据·数据仓库·flink
juniperhan20 小时前
Flink 系列第6篇:Watermark 水印全解析(原理+实操+避坑)
大数据·数据仓库·flink
武子康1 天前
大数据-264 实时数仓-MySQL Binlog配置详解:从原理到实践|数据恢复与主从复制实战
大数据·hadoop·后端
武子康1 天前
大数据-265 实时数仓-Canal MySQL Binlog配置详解:从原理到实践|数据恢复与主从复制实战
大数据·hadoop·后端
晓纪同学1 天前
WPF-03 第一个WPF程序
大数据·hadoop·wpf
2501_933329552 天前
技术深度剖析:Infoseek 字节探索舆情处置系统的全链路架构与核心实现
大数据·数据仓库·人工智能·自然语言处理·架构
xiaoyaohou112 天前
024、大数据技术栈概览:Hadoop、Spark与Flink
大数据·hadoop·spark
虚幻如影2 天前
Hive 中“STRING类型无需显式指定长度
数据仓库·hive·hadoop
荒川之神2 天前
Oracle 数据仓库雪花模型设计(完整实战方案)
数据库·数据仓库·oracle