deterministic 在 mysql 5.7 中仅是行为承诺,不提升性能,优化器完全忽略该标记;真正影响性能的是函数内部逻辑,如表访问、循环处理或随机函数调用。

在 MySQL 5.7 中,DETERMINISTIC 关键字本身不提升函数执行速度,但它影响优化器是否缓存函数结果——而这种缓存只在极少数场景下生效,多数情况下你加了也白加。
MySQL 5.7 不支持 DETERMINISTIC 函数的执行计划缓存
MySQL 直到 8.0.13 才开始在排序、分组、临时表构建等阶段真正利用 DETERMINISTIC 声明做结果复用;5.7 的优化器完全忽略该标记对执行计划的影响。也就是说:
- 即使你写了
DETERMINISTIC,WHERE my_func(col) = 'x'依然会对每一行调用一次函数 -
ORDER BY my_func(col)不会提前计算并缓存值,而是每排序比较时都重新执行 - 函数索引在 5.7 根本不存在,
CREATE INDEX ON t((UPPER(name)))直接报错ERROR 1064
不加 DETERMINISTIC 就建不了函数(但加错更危险)
MySQL 5.7 启用 binlog(即默认生产配置)时,强制要求函数声明行为特性,否则创建失败:
- 没写
DETERMINISTIC、NO SQL或READS SQL DATA→ 报错ERROR 1418 - 逻辑上只读表却误标
DETERMINISTIC→ 优化器不会缓存,但主从复制可能出错(从库执行时看到不同快照) - 含
SELECT ... FROM users却标DETERMINISTIC→ 表数据一更新,函数返回就不可信,且无法用于 CHECK 约束
真正影响性能的是函数内部逻辑,不是 DETERMINISTIC 声明
你在 5.7 里写的函数慢,99% 和声明无关,而和它干了什么有关:
- 访问表(哪怕只查一行)→ 触发额外查询、锁等待、网络往返
- 字符串循环处理(如逐字符校验身份证号)→ CPU 消耗随输入长度线性增长
- 调用
RAND()、NOW()、UUID()→ 这些在 5.7 必须标NOT DETERMINISTIC,否则语法拒绝 - 参数是字段(如
my_func(name))→ 每行都重算;参数是常量(如my_func('abc'))→ 可能被优化器提前求值
别花时间纠结要不要加 DETERMINISTIC 来“优化”,先看函数体里有没有 SELECT、有没有循环、有没有跨表关联——那些才是真瓶颈。5.7 的 DETERMINISTIC 就是个“行为承诺书”,不是加速器。











