← 返回首页

select * 为什么不推荐使用

在 SQL 查询中,虽然 SELECT * 看起来非常省事,但在生产环境和实际开发中通常被强烈不推荐。这主要是因为它会在性能、代码维护以及安全性三个方面带来严重的隐患:

1. 性能与资源消耗问题

  • 增加 I/O 与网络开销:SELECT * 会返回表中所有的字段,包括业务并不需要的列,甚至是大文本字段(如 TEXT、BLOB、JSON)。这会显著增加数据库的磁盘 I/O 压力和网络带宽的传输负担。
  • 内存占用飙升:应用层需要处理这些冗余数据并将其加载到内存中。在高并发场景下,多余的数据会挤占缓存(如 Buffer Pool),甚至可能导致内存溢出(OOM)和应用崩溃。
  • 导致索引失效:使用 SELECT * 时,数据库优化器通常会放弃“覆盖索引”(Covering Index),因为索引无法包含所有列的数据。这会强制数据库进行“回表”操作或全表扫描,大幅降低查询效率。

2. 代码维护性与稳定性风险

  • 表结构变更引发连锁反应:应用代码如果依赖 SELECT *,实际上就隐式耦合了表的当前结构。一旦 DBA 或后端新增、删除或重命名了字段,返回结果的列顺序和数量就会改变,极易导致应用层解析报错或静默出错。
  • 多表 JOIN 时的列名冲突:在多表联查时使用 SELECT *,如果多个表中存在同名字段(例如都有 id 或 name),结果集中的同名列会被覆盖,导致数据错乱。
  • 降低代码可读性:显式写出所需字段能让后续维护者清晰地了解该查询的业务意图,而 SELECT * 则让查询逻辑变得模糊不清。

3. 安全与合规隐患

  • 敏感数据泄露风险:如果表中包含密码哈希、Token、身份证号等敏感字段,SELECT * 会将它们一并查出。即便前端不展示,这些数据也会在网络中传输并驻留在内存中,增加了被截获或意外记录到日志中的风险。

最佳实践与例外场景

正确做法:始终显式指定业务所需的字段(例如 SELECT id, name FROM users),并在多表联查时为同名字段加上明确的别名。

可以谨慎使用 SELECT * 的少数场景:

  1. 临时排查问题:在开发或测试环境中快速探查数据样例(如 SELECT * FROM users LIMIT 5),但不应提交到生产代码中。
  2. 统计行数或判断存在性:当星号代表行而非具体列时,例如 SELECT COUNT(*) FROM table 或 EXISTS (SELECT * ...),这是合理的用法。