You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL不同返回结果的SELECT查询耗时异常问题咨询

问题描述

我有一张约7000行数据的简单表,对其执行完全相同的WHERE条件的MySQL查询10000次,仅修改SELECT子句的返回内容,结果耗时差异远超预期:原本以为返回固定值SELECT 1的查询最快,返回全量字段SELECT *的最慢,但实际结果完全相反。

MySQL版本为5.7.40。

单次测试耗时

  • 4.5993759632111 秒
SELECT * FROM mytable WHERE 145109811 BETWEEN start AND end LIMIT 1
  • 5.3308868408203 秒
SELECT ID FROM mytable WHERE 145109811 BETWEEN start AND end LIMIT 1
  • 7.7556929588318 秒
SELECT 1 FROM mytable WHERE 145109811 BETWEEN start AND end LIMIT 1 

三轮重复测试结果

为排除数据库状态影响,将三种查询放入同一脚本,按不同顺序执行三轮测试:

第一轮顺序:SELECT 1 → SELECT * → SELECT ID

10:19:58 - SELECT 1  - 7.3224468231201 sec.
10:20:03 - SELECT *  - 4.6961460113525 sec.
10:20:08 - SELECT ID - 4.4760630130768 sec.
10:20:28 - SELECT 1  - 7.4960129261017 sec.
10:20:32 - SELECT *  - 4.4980108737946 sec.
10:20:37 - SELECT ID - 4.4355578422546 sec.
10:21:00 - SELECT 1  - 8.0782158374786 sec.
10:21:04 - SELECT *  - 4.4764659404755 sec.
10:21:09 - SELECT ID - 4.273129940033 sec.

第二轮顺序:SELECT * → SELECT ID → SELECT 1

10:22:23 - SELECT *  - 6.5342800617218 sec.
10:22:28 - SELECT ID - 5.1359310150146 sec.
10:22:35 - SELECT 1  - 7.1028819084167 sec.
10:22:52 - SELECT *  - 4.8350520133972 sec.
10:22:57 - SELECT ID - 4.4192798137665 sec.
10:23:04 - SELECT 1  - 6.9962570667267 sec.
10:23:18 - SELECT *  - 5.2138640880585 sec.
10:23:22 - SELECT ID - 4.3040509223938 sec.
10:23:30 - SELECT 1  - 7.1998341083527 sec.

第三轮顺序:SELECT ID → SELECT 1 → SELECT *

10:24:05 - SELECT ID - 4.7385289669037 sec.
10:24:12 - SELECT 1  - 7.1701371669769 sec.
10:24:17 - SELECT *  - 4.5180490016937 sec.
10:24:33 - SELECT ID - 5.6322748661041 sec.
10:24:41 - SELECT 1  - 7.4376618862152 sec.
10:24:45 - SELECT *  - 4.4281830787659 sec.
10:25:00 - SELECT ID - 5.3789880275726 sec.
10:25:07 - SELECT 1  - 7.3066239356995 sec.
10:25:12 - SELECT *  - 4.5297379493713 sec.

总耗时统计

SELECT *    39.03364301 sec.
SELECT ID   42.79380441 sec.
SELECT 1    66.11007166 sec.

原因分析

这种反直觉的结果主要和MySQL 5.7的执行引擎处理逻辑、聚簇索引特性有关,具体可以从这几个角度解释:

1. 聚簇索引的直接读取优势

你的表是InnoDB引擎(默认),主键ID对应的聚簇索引叶子节点存储了整行数据:

  • 执行SELECT *时,找到符合BETWEEN条件的行后,直接从聚簇索引叶子节点读取整行数据返回,不需要额外IO或数据拼接。
  • 执行SELECT ID时,虽然只需要主键值,但同样是直接从聚簇索引读取,不过服务器层需要过滤掉其他列,有极少量额外开销,所以比SELECT *稍慢。

而SELECT 1的情况,MySQL找到符合条件的行后,不能直接从索引/数据行中读取现成的值,需要服务器层动态生成常量1返回。这个生成操作单次开销极小,但在10000次重复执行的场景下,累积的开销就会被放大,导致总耗时显著增加。

2. 优化器的执行计划差异

在MySQL 5.7中,对于SELECT 1这类返回常量的查询,优化器可能不会触发和SELECT */SELECT ID相同的“快速返回”优化:

  • 虽然三个查询都用了LIMIT 1,找到第一个符合条件的行就停止扫描,但SELECT 1的执行流程中,服务器层需要额外处理“常量生成”的逻辑,导致每个查询的执行周期变长。
  • 对比之下,SELECT *和SELECT ID都是直接读取已有数据,执行流程更简洁,单查询耗时更短。

3. 缓存与执行上下文的影响

虽然你做了多轮不同顺序的测试,但SELECT *和SELECT ID的结果是从聚簇索引读取的实际数据,更容易被MySQL的缓存机制(如InnoDB缓冲池)命中;而SELECT 1返回的是动态生成的常量,无法利用数据缓存的优势,每次执行都需要重新生成,进一步拉开了耗时差距。


内容的提问来源于stack exchange,提问作者Junior

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:50:20