避免 SELECT * 是 MySQL 查询优化的基础,因它导致冗余 I/O、网络开销、回表失效、逻辑脆弱;应明确字段、善用覆盖索引、检查 ORM 配置、定期审查慢日志。

避免 SELECT * 是 MySQL 查询优化中最基础也最关键的一步。它不仅影响性能,还埋下维护隐患。
为什么 SELECT * 会拖慢查询
数据库需要读取并传输表中所有字段,哪怕你只用其中一两个。如果表有大量字段、大文本(如 TEXT、BLOB)或已建立覆盖索引,* 会让 MySQL 放弃高效路径,转而回表查全字段,增加 I/O 和网络开销。另外,字段顺序变更、新增字段都可能意外破坏应用逻辑。
明确列出所需字段
只写真正需要的列名,不省事,不偷懒。即使看起来“就多几个字段”,积少成多也会显著影响响应时间和内存使用。
- ✅ 正确:
SELECT user_id, username, email FROM users WHERE status = 1 - ❌ 避免:
SELECT * FROM users WHERE status = 1
善用覆盖索引减少回表
当 SELECT 的字段全部被某个索引包含时,MySQL 可直接从索引中获取数据,无需访问主键聚簇索引(即“回表”)。这是提升查询速度的重要手段。
- 例如:对
users(status, user_id, username)建联合索引,再执行SELECT user_id, username FROM users WHERE status = 1,就能走覆盖索引 - 但若写了
SELECT *,即使有该索引,仍需回表取其他字段,覆盖失效
注意 ORM 框架默认行为
很多 ORM(如 Laravel Eloquent、Django ORM、MyBatis)默认生成 SELECT *。务必检查文档,主动指定字段:
- Laravel:
User::select('id', 'name')->where('active', 1)->get() - Django:
User.objects.values('id', 'name').filter(active=True) - MyBatis:在 XML 中明确写
,而非依赖自动映射
定期审查慢查询日志中的 SELECT *
开启慢查询日志(slow_query_log=ON),配合 pt-query-digest 或 MySQL 自带的 mysqldumpslow 工具,筛选出高频、高耗时的 SELECT * 查询,逐个优化。
不复杂但容易忽略。养成习惯后,性能和可维护性都会明显提升。










