mysql函数执行慢怎么办_mysql性能优化方法

来源:这里教程网 时间:2026-02-28 20:48:43 作者:

为什么
EXPLAIN
看起来没问题,但函数调用还是慢?

MySQL 中自定义函数(UDF)或内置函数(如

DATE_FORMAT()
JSON_EXTRACT()
)在 WHERE 或 SELECT 中高频使用时,常成为性能瓶颈——即使
EXPLAIN
显示走了索引,实际执行仍卡顿。根本原因在于:函数会阻止索引下推(Index Condition Pushdown),甚至导致全表扫描;更隐蔽的是,标量函数在每行数据上重复执行,无法被优化器提前剪枝。

实操建议:

避免在
WHERE
子句中对索引列使用函数,例如把
WHERE DATE(create_time) = '2024-01-01'
改成
WHERE create_time >= '2024-01-01' AND create_time 
对 JSON 字段慎用
JSON_EXTRACT()
做条件过滤,优先考虑生成虚拟列并建索引:
ALTER TABLE t ADD COLUMN status INT AS (JSON_EXTRACT(data, '$.status')) STORED, ADD INDEX idx_status(status)
确认函数是否为「确定性」(DETERMINISTIC):非确定性函数(如含
NOW()
RAND()
)无法被缓存,且可能干扰查询重写

哪些 MySQL 函数天生就慢?怎么绕开?

不是所有函数都适合线上高频调用。以下几类需特别警惕:

LIKE '%xxx'
:左侧通配符必然放弃索引,改用全文索引(
FULLTEXT
)或倒排表 + ES 同步
CONCAT()
在大字段上拼接(尤其含
TEXT
类型)会触发隐式转换和临时表,可提前在应用层拼接或用生成列固化
GROUP_CONCAT()
ORDER BY
时行为不可控,且受
group_concat_max_len
限制,超长会被截断;若用于分组聚合展示,优先考虑应用层组装
MD5()
/
SHA1()
等哈希函数 CPU 开销大,批量计算时易拖慢 QPS,应尽量前置到写入阶段计算并存储

如何定位是函数本身慢,还是函数+数据联合慢?

单看慢日志(

slow_query_log
)只能知道整条 SQL 慢,无法拆解函数耗时。必须结合运行时诊断:

启用
performance_schema
并查询
events_statements_history_long
,过滤出含函数名的 SQL,观察
TIMER_WAIT
LOCK_TIME
占比
sys.statement_analysis
视图快速识别高延迟函数调用模式,例如:
SELECT * FROM sys.statement_analysis WHERE query LIKE '%JSON_EXTRACT%'
对疑似慢函数做隔离测试:单独执行
SELECT func(col) FROM t LIMIT 1000
,对比
SELECT col FROM t LIMIT 1000
的执行时间,差值即为函数开销基准

UDF 和存储函数有哪些隐藏代价?

自定义函数(尤其是 C/C++ 编写的 UDF)看似灵活,但极易引入稳定性与性能问题:

UDF 每次调用都需跨用户态/内核态,上下文切换成本高;若函数内部有网络/磁盘 I/O(比如调外部 HTTP 接口),会彻底阻塞整个连接线程 存储函数(
CREATE FUNCTION
)默认以
DETERMINISTIC
声明,但若实际非确定却未声明
NOT DETERMINISTIC
,会导致主从不一致或复制中断
函数返回值类型不匹配(如定义为
INT
却返回字符串)会触发隐式转换,且该转换发生在每一行,放大 CPU 使用率
MySQL 8.0+ 对函数内联支持有限,无法像 PostgreSQL 那样自动内联展开,复杂逻辑仍需解释执行

真正棘手的从来不是“怎么写函数”,而是“要不要在这里用函数”。多数场景下,把计算逻辑下沉到应用层、或用物化视图/汇总表预计算,比硬扛一个慢函数更可靠。

相关推荐