避免 SELECT * 是 MySQL 查询优化的基础,因它导致冗余 I/O、网络开销、回表失效、逻辑脆弱;应明确字段、善用覆盖索引、检查 ORM 配置、定期审查慢日志。
避免 SELECT * 是 MySQL 查询优化中最基础也最关键的一步。它不仅影响性能,还埋下维护隐患。
数据库需要读取并传输表中所有字段,哪怕你只用其中一两个。如果表有大量字段、大文本(如 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 st
atus = 1,就能走覆盖索引SELECT *,即使有该索引,仍需回表取其他字段,覆盖失效很多 ORM(如 Laravel Eloquent、Django ORM、MyBatis)默认生成 SELECT *。务必检查文档,主动指定字段:
User::select('id', 'name')->where('active', 1)->get()
User.objects.values('id', 'name').filter(active=True)
,而非依赖自动映射开启慢查询日志(slow_query_log=ON),配合 pt-query-digest 或 MySQL 自带的 mysqldumpslow 工具,筛选出高频、高耗时的 SELECT * 查询,逐个优化。
不复杂但容易忽略。养成习惯后,性能和可维护性都会明显提升。