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

如何让Aurora MySQL 8.x中CTE仅调用一次expensive函数?

解决Aurora MySQL 8.x中函数被重复调用的问题

在你的场景里,尽管CTE逻辑上只返回一行数据,但因为后续和children表做关联,MySQL优化器会把CTE的执行和关联操作合并,导致expensive()函数被每一条子记录触发一次调用。哪怕给函数加上DETERMINISTIC属性也没用——因为这个函数带有插入calls表的副作用,优化器不会缓存这类有副作用的函数结果。

下面是两种能确保函数只执行一次的调整方案:

方案1:用用户变量存储函数结果

先单独调用一次函数,把结果存到变量里,后续查询直接用这个变量。这种方式最直观,能彻底保证函数只执行一次。

set @pParentId = 2;
-- 提前调用函数,将结果存入变量
set @func_result = sandpit.expensive(@pParentId);

SELECT p.*, c.*, @func_result as result
FROM sandpit.parents p
LEFT OUTER JOIN sandpit.children c ON c.parentId = p.id
WHERE p.id = @pParentId;

方案2:用独立子查询强制函数单次执行

把函数调用放在一个完全独立的子查询里,用from dual和limit 1确保子查询只执行一次,再通过CROSS JOIN把结果关联到主查询中:

set @pParentId = 2;

SELECT p.*, c.*, func_result.result
FROM sandpit.parents p
LEFT OUTER JOIN sandpit.children c ON c.parentId = p.id
-- 独立子查询获取函数结果,确保只执行一次
CROSS JOIN (
    select sandpit.expensive(@pParentId) as result
    from dual
    limit 1
) as func_result
WHERE p.id = @pParentId;

这两种方案都能让expensive()函数只执行一次,同时把结果返回给所有同parentId的子行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 07:33:24