← 返回首页
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 * 的少数场景:
- 临时排查问题:在开发或测试环境中快速探查数据样例(如
SELECT * FROM users LIMIT 5),但不应提交到生产代码中。 - 统计行数或判断存在性:当星号代表行而非具体列时,例如
SELECT COUNT(*) FROM table或EXISTS (SELECT * ...),这是合理的用法。