避免
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 中明确写 <result column="id" property="id"></result>,而非依赖自动映射
定期审查慢查询日志中的 SELECT *
开启慢查询日志(
slow_query_log=ON),配合
pt-query-digest或 MySQL 自带的
mysqldumpslow工具,筛选出高频、高耗时的
SELECT *查询,逐个优化。
不复杂但容易忽略。养成习惯后,性能和可维护性都会明显提升。
