说实话,在做MySQL复杂查询的性能压测时,最让人头疼的就是“压了个寂寞”——数据是伪造的、索引对不上、SQL模板走了不同的执行计划,最后跑出来的指标跟生产环境毫无关联。这篇文章就系统性地梳理一遍,如何借助Qwen大模型生成靠谱的压测数据,以及如何把整条链路走通、走稳。

准备压测所需的MySQL表结构与索引
压测前的第一要务,不是急着写SQL,而是确认表结构和索引。需要压测的复杂查询所依赖的表必须已经存在,字段类型、主键、外键、联合索引都要和生产环境保持一致。例如,一个查询里包含WHERE status = 'active' AND created_at > '2025-01-01'再加上ORDER BY score DESC LIMIT 50,那么(status, created_at)或者(status, created_at, score)上的覆盖索引是必不可少的。
如何确认?直接执行SHOW CREATE TABLE your_table;,对照DDL逐项检查。缺失关键索引会让压测结果完全失真——即便Qwen生成的数据再逼真,也救不了因索引缺失导致的满表扫描问题。
用Qwen生成符合业务分布的模拟数据SQL
打开Qwen2.5-Coder-1.5B-Instruct或Qwen3.5-2B模型,输入自然语言指令就能生成数据。这里提供两种常见做法:
方法一:指定分布特征直接生成INSERT语句。比如“生成10万条用户订单记录的INSERT语句,要求:user_id在1~10000间均匀分布;order_status取值为'pending'(40%)、'paid'(55%)、'cancelled'(5%);amount在50~5000之间服从对数正态分布;created_at集中在2025年全年,但Q4占比60%;所有字段需符合orders表结构:id BIGINT AUTO_INCREMENT, user_id INT, order_status VARCHAR(20), amount DECIMAL(10,2), created_at DATETIME”。
方法二:基于现有样本推演扩展。如果手头有几条真实数据,可以让模型模仿其风格生成更多。例如“已知以下5条真实订单数据:[(101,'paid',899.00,'2025-03-12 14:22:05'),(207,'pending',120.50,'2025-01-08 09:11:33')...],请据此生成99995条风格一致的新数据,保持字段间逻辑关系(如高金额订单更倾向paid状态)”。
必须补全表结构定义:如果在提示词里没给出完整的CREATE TABLE语句,模型可能会误判字段长度、是否允许NULL、默认值,导致INSERT失败或数据截断。
将生成SQL安全导入MySQL并校验数据质量
数据生成后,导入需要几道工序:第一,把Qwen输出的INSERT语句存成mock_data.sql,手动去掉代码块标记(```sql和```);第二,关闭MySQL的唯一键和外键检查,加速导入:SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;;第三,用mysql客户端执行:mysql -u root -p your_db < mock_data.sql;第四,立刻校验关键字段的分布情况:SELECT order_status, COUNT(*) FROM orders GROUP BY order_status;,看比例是否接近设定值;第五,运行ANALYZE TABLE orders;更新统计信息,否则后续EXPLAIN会误判行数。
这一步千万不能跳过。即使INSERT成功了,若没跑ANALYZE TABLE,优化器依然按旧统计估算执行计划,压测时看到的“慢查询”很可能只是统计过期造成的假象。
构造与真实查询完全一致的压测SQL模板
从生产日志或慢查询日志里把原始SQL直接复制出来,把其中的字面量替换成参数占位符。比如WHERE user_id = 12345 AND created_at >= '2025-04-01'改成WHERE user_id = ? AND created_at >= ?。
关键是要确保改写后SQL的执行计划跟原SQL完全一致。分别在MySQL里对二者执行EXPLAIN FORMAT=TREE,比对访问类型、索引使用、预估行数,三处必须一字不差。如果发现差异,说明占位符位置或类型影响了优化器决策——这时需要在占位符后显式加类型转换,比如WHERE user_id = CAST(? AS SIGNED) AND created_at >= CAST(? AS DATETIME)。
用sysbench或mysqlslap注入参数化查询进行压力测试
最后一步是真正的压力测试。准备参数文件query_params.txt,每行一组参数,格式为12345,2025-04-01 00:00:00;然后启动mysqlslap,指定参数文件并启用并发:mysqlslap --host=localhost --user=root --password=xxx --create-schema=your_db --query="SELECT * FROM orders WHERE user_id = ? AND created_at >= ?" --concurrency=64 --iterations=1000 --delimiter="," --pre-system="SET SESSION sort_buffer_size = 4194304;" --post-system="RESET QUERY CACHE;" --csv=/tmp/slap_result.csv -F ",";观察输出中的A verage number of seconds to run all queries和Queries per second a vg两项数值;同时查看MySQL的SHOW PROCESSLIST;和SHOW ENGINE INNODB STATUS\G,确认有没有锁等待、Buffer Pool命中率骤降等隐性瓶颈。
