MySQLslap测SELECT响应时间不准,因其仅提供平均值和总耗时,缺乏P95/P99等单次耗时分布;需用--no-defaults、--query指定真实SQL、--concurrency=1+--iterations=100逐条测量,并加--verbose排除连接干扰。

MySQLslap 测 SELECT 响应时间,为什么总不准
因为 mysqlslap 默认不记录单次查询耗时分布,只给平均值和总耗时,P95/P99 响应时间完全不可见。它把 500 次 SELECT 当成一个黑盒批次跑完再统计,中间抖动、长尾请求全被抹平。
真正要分析 SELECT 响应时间,得让它“逐条测、逐条记”:
- 必须加
--no-defaults避免读取全局配置干扰连接行为 - 用
--query指向含真实 WHERE 条件的 SQL 文件,别信--auto-generate-sql生成的假数据 - 设
--concurrency=1+--iterations=100,才能拿到 100 个独立响应时间点,后续导出用 Excel 算 P95 - 加
--verbose可看到每轮连接建立/销毁开销,排除网络或认证延迟干扰
sysbench 跑 OLTP 场景时,如何单独提取 SELECT 的 RT
sysbench 的 oltp_read_only 模式看似只做读,但默认混合了 POINT_SELECT、INDEX_RANGE、SCAN 三类查询,响应时间是加权平均值,不能代表你那条关键 SELECT id,name FROM users WHERE status=? 的真实表现。
要精准盯住某类 SELECT:
- 改用
oltp_common模式,配合自定义 Lua 脚本,在thread_init里预编译语句,event中只执行目标查询 - 禁用
--time改用--events=10000,避免时间截断导致样本不均 - 输出日志加
--report-interval=1,再用 awk 提取queries:行里的latency字段,过滤出type: point_select的原始毫秒值 - 注意:sysbench 3.0+ 才支持 per-query latency 输出,旧版本需打 patch 或换
pt-query-digest解析 slow log
EXPLAIN 不显示响应时间,怎么知道 SELECT 实际卡在哪
EXPLAIN 只告诉你“计划怎么走”,不告诉你“走得多慢”。比如看到 type: range + rows: 12000,你以为慢在扫描,结果可能是 buffer pool 没预热,第一次访问全磁盘 IO;也可能是锁等待,EXPLAIN 根本不体现。
定位真实瓶颈得组合查:
- 开
performance_schema,查events_statements_history_long,过滤你的 SQL 文本,看TIMER_WAIT(实际耗时)、LOCK_TIME(锁等待)、ROWS_AFFECTED(是否真扫了那么多行) - 执行前先
SELECT SLEEP(0.001)占位,再跑目标 SELECT,用SHOW PROFILE FOR QUERY N看各阶段耗时(如Creating sort index占 80%,说明ORDER BY没走索引) - 对高并发 SELECT,抓
INFORMATION_SCHEMA.INNODB_TRX和INNODB_LOCK_WAITS,确认是不是被 UPDATE/DELETE 持锁阻塞
用 Python 脚本做 SELECT 基准测试,绕不开的三个坑
手写脚本看似灵活,但容易在连接管理、时钟精度、结果归一化上翻车。
常见陷阱:
- 没复用连接:每次
cursor.execute()都新建 TCP 连接,测出来全是三次握手+SSL 开销,不是 SQL 本身耗时 → 必须用连接池,如SQLAlchemy.create_engine(pool_pre_ping=True) - 用
time.time()测毫秒级差异,Windows 下精度只有 15ms,Linux 也常受系统调度影响 → 改用time.perf_counter(),且每个 query 单独调用,不跨循环累加 - 没清 buffer pool:第一次跑慢,后面全缓存,结果不可比 → 测试前执行
SET GLOBAL innodb_buffer_pool_dump_now=ON+SET GLOBAL innodb_buffer_pool_load_now=OFF强制冷启动
最易被忽略的是查询参数绑定方式:用 cursor.execute("SELECT * FROM t WHERE id = %s", (x,)) 是安全的,但若拼接字符串 "SELECT * FROM t WHERE id = " + str(x),MySQL 会为每个不同 x 生成新执行计划,缓存失效,RT 波动剧烈。










