<p>SELECT * 会显著降低性能并引发错误:导致全表扫描、索引失效(无法走覆盖索引)、增大IO与网络开销、降低缓存效率,并带来隐式耦合风险;应明确指定所需字段以提升查询效率与稳定性。</p>

SELECT * 一写就慢,还容易出错
别图省事写 SELECT *,它不只是多查几个字段那么简单。真实场景里,user_info 表里有个 avatar 字段存的是 Base64 图片,你只想要 id 和 username,结果却把几 MB 的图片全拉下来——网络卡、内存爆、应用解析失败都可能发生。
更隐蔽的问题是索引失效:SELECT id, username FROM user_info WHERE city = '北京' 如果 city 和 username 都在联合索引里,就能走覆盖索引;但 SELECT * 必须回表读整行,性能直接掉一档。
- 写之前先问自己:业务逻辑真正用到哪几个字段?只写它们
- 用
EXPLAIN看执行计划,如果Extra列出现Using index,说明命中了覆盖索引 - 建表时避免把大字段(如
TEXT、BLOB)和高频查询字段混在同一张表里
DISTINCT 不是“去重某列”,而是“去重整行”
新手常以为 DISTINCT City 是只对 City 去重,其实它是对 SELECT 后面所有列的组合去重。比如 SELECT DISTINCT City, Province FROM customers,哪怕两个城市名一样,只要省份不同,就会保留两条。
想只取不重复的城市?就得写成 SELECT DISTINCT City FROM customers,且不能带其他非聚合、非分组字段。否则 MySQL 会直接报错:ERROR 1055: Expression #2 of SELECT list is not in GROUP BY clause(开启严格模式时)。
- 多列查询时,
DISTINCT作用范围是整行,不是单列 - 需要按某列去重但又想带其他字段?改用
GROUP BY City+ 聚合函数,比如MAX(id) -
DISTINCT内部要排序+去重,10 万行数据比GROUP BY略快但内存占用更高,大数据量慎用
WHERE 条件漏写或写错,轻则结果错,重则删库跑路
没加 WHERE 的 UPDATE 或 DELETE 是线上事故头号诱因。比如 UPDATE student SET age = 18 —— 全班学生年龄瞬间变 18,备份都没法救。
更常见的是条件写错:把 WHERE id = 123 写成 WHERE id = '123' 看似一样,但如果 id 是 BIGINT 类型,MySQL 会隐式转成数字再比,看似没报错,但可能触发全表扫描(尤其没索引时)。
- 写完
UPDATE/DELETE,第一反应不是执行,而是先改成SELECT验证:SELECT * FROM student WHERE id = 123 - 字符串值必须用单引号,数值不用引号,类型必须和字段定义一致
- 开发环境开事务,执行前加
BEGIN;,确认无误再COMMIT;,误操作还能ROLLBACK;
字段名、表名拼错,错误信息根本不告诉你哪错了
报错 Unknown column 'agee' in 'field list' 还算友好;更常见的是 Table 'db.users' doesn't exist —— 你明明建的是 user 表,却写了 users;或者大小写不一致,在 Linux 下 MySQL 默认区分表名大小写。
还有关键字当字段名:比如字段叫 order,不加反引号直接写 SELECT order FROM sales,MySQL 把 order 当成了 ORDER BY 关键字,直接语法报错。
- 写 SQL 前先用
DESCRIBE table_name;或SHOW COLUMNS FROM table_name;确认字段名和类型 - 字段/表名含空格、关键字、特殊符号,必须用反引号包裹:
SELECT `order` FROM `sales` - 关键字一律大写(
SELECT、FROM),字段名小写,视觉上立刻区分开,减少拼错概率
实际写的时候,最危险的不是不会,而是“看起来能跑通”。比如 WHERE name = NULL 永远不成立,得写 WHERE name IS NULL;比如子查询返回多行却用了 =,得换 IN。这些坑不报语法错,但结果永远不对。

















