[TOC] #### 1. 前言 --- 刚学 MySQL 的时候,很多人最喜欢写的一句 SQL 就是: ```sql SELECT * FROM users; ``` 简单、方便、字段全都查出来,尤其是在测试阶段,随手一写就能看到表里的所有数据 但到了真实项目里,很多公司都会要求:不要随便写 `SELECT *` 那问题来了:`SELECT *` 明明这么方便,为什么不建议用 ? #### 2. SELECT \* 是什么意思 --- `SELECT *` 的意思是:查询这张表里的所有字段 比如 `users` 表里有这些字段: ```plaintext id username phone email password avatar created_at updated_at ``` 你写: ```sql SELECT * FROM users; ``` MySQL 就会把这些字段全部查出来 看起来没什么问题,但真正的问题是:你不一定真的需要这么多字段 比如页面上只展示用户名和头像,那其实只需要: ```sql SELECT username, avatar FROM users; ``` 其它字段查出来,就是多余的 #### 3. 第一个问题:浪费网络传输 --- 数据库查出来的数据,最终要从 MySQL 传到后端服务 如果你只需要 2 个字段,却查了 20 个字段,那多出来的 18 个字段,就会白白占用网络传输 数据量小的时候可能看不出来,但如果一张表有几十万条数据,或者某些字段特别大,比如: ```plaintext content description remark json_data ``` 这些字段一旦被 `SELECT *` 查出来,接口就可能变慢 不是因为 MySQL 一定查不动,而是因为查了很多根本用不到的数据 #### 4. 第二个问题:影响索引优化 --- 很多时候,MySQL 可以通过索引直接返回结果 比如你有一个索引: ```plaintext KEY idx_username (username) ``` 然后只查 `username`: ```sql SELECT username FROM users WHERE username = 'Tom'; ``` 这种情况下,MySQL 可能只看索引就能拿到结果,不需要再回到表里查完整数据,这就是常说的覆盖索引 但如果写的是: ```sql SELECT * FROM users WHERE username = 'Tom'; ``` 那 MySQL 不光要通过索引找到数据,还要回到表里把所有字段都取出来 字段越多,代价越高,所以 `SELECT *` 有时候会让原本可以很快的查询,变得没那么快 #### 5. 第三个问题:字段变化容易影响代码 --- 还有一个很现实的问题:表结构不是永远不变的 今天 `users` 表有 8 个字段,明天可能加一个字段: ```plaintext status ``` 后天可能又加一个字段: ```plaintext extra_info ``` 如果你的代码里大量使用 `SELECT *`,那么表字段一变,查询结果也会跟着变 有些代码可能依赖字段顺序,有些接口可能会把不该返回的字段也返回出去,比如用户表里的: ```plaintext password salt token ``` 这些字段如果被 `SELECT *` 查出来,再不小心返回给前端,就很危险 所以明确写字段,也是在保护代码边界,查什么,就返回什么 #### 6. 第四个问题:可读性不好 --- 写 SQL 不只是给数据库看的,也是给人看的 比如这句: ```sql SELECT * FROM orders WHERE user_id = 1001; ``` 只看 SQL,很难知道这个接口到底需要订单的哪些信息 但如果写成下面这样就很清楚了,这个接口需要订单号、金额、状态和创建时间,后面别人维护代码时,也更容易理解 ```sql SELECT id, order_no, total_amount, status, created_at FROM orders WHERE user_id = 1001; ``` #### 7. 那 SELECT * 完全不能用吗 --- 也不是。在一些场景下,用 `SELECT *` 没什么问题。 比如本地调试: ```sql SELECT * FROM users LIMIT 10; ``` 比如临时查数据、学习阶段看表结构,这些都可以 真正不建议的是:在正式项目代码里,尤其是接口查询、列表查询、定时任务、大数据量查询里,长期使用 `SELECT *` #### 8. 实际开发建议 --- 平时写 SQL,可以养成一个习惯:需要什么字段,就查什么字段 比如列表页: ```sql SELECT id, title, created_at FROM articles; ``` 详情页: ```sql SELECT id, title, content, created_at FROM articles WHERE id = 1001; ``` 后台管理页: ```sql SELECT id, username, phone, status, created_at FROM users; ``` 这样虽然多写了几个字段名,但后面会少很多问题 #### 9. 本文小结 --- 为什么不建议 `SELECT *` ? 主要有几个原因: + 会查出很多用不到的字段 + 增加网络传输和内存消耗 + 可能影响索引优化 + 表结构变化时更容易影响代码 + 可能把敏感字段查出来 所以在正式项目里,更推荐这样写: ```sql SELECT id, username, avatar FROM users; ``` 而不是: ```sql SELECT * FROM users; ``` 一句话总结:`SELECT *` 不是不能用,而是不要在项目代码里随便用 查什么字段,就写什么字段,这才是更稳的写法