MySQL 5.7 不使用存储过程临时表的数组变量性能优化咨询
MySQL数组变量性能问题解决方案
性能差根因
Query 3使用FIND_IN_SET匹配索引列时,会导致索引无法触发range扫描,只能走全索引扫描逐行校验匹配,数据量越大性能损耗越明显,和Query 1的range扫描效率有数量级差距。
可行方案(无存储过程/临时表)
使用预处理语句动态拼接IN查询,既可以把数组存入变量,又能完全复用索引性能,和直接写常量IN查询的执行计划完全一致。
操作示例
-- 1. 定义数组变量,字符串类型元素需要提前包裹单引号 SET @transactionNos = "'10001','10004'"; -- 2. 拼接动态查询SQL SET @querySql = CONCAT('SELECT * FROM `order` WHERE transaction_no IN (', @transactionNos, ')'); -- 3. 预处理并执行SQL PREPARE exec_stmt FROM @querySql; EXECUTE exec_stmt; DEALLOCATE PREPARE exec_stmt;
执行计划验证
上述语句的执行计划和Query 1完全一致,type为range,命中uk_transaction_no索引,扫描行数仅为匹配的2行,无性能损耗。
注意事项
- 如果数组元素为数值类型,变量内不需要加单引号,直接写数值逗号分隔即可。
- 如果数组内容来自外部用户输入,需要提前做内容合法性校验,避免SQL注入风险。
内容的提问来源于stack exchange,提问作者oka96
相关产品推荐
相关产品推荐

