生产环境应避免SELECT *,需明确指定字段并加表别名;NULL判断必须用IS NULL/IS NOT NULL;ORDER BY须配合LIMIT及合理索引,推荐游标分页。

SELECT * FROM 表名会查出所有字段,但生产环境要避免这么写
直接用 SELECT * 看起来省事,实际会拖慢查询、增加网络传输量,还可能因表结构变更导致应用报错(比如新增了大字段 TEXT 或 BLOB)。更关键的是,ORM 或前端映射时字段顺序错位容易引发静默错误。
实操建议:
- 明确列出需要的字段,例如
SELECT id, name, created_at FROM users - 如果字段来自多表关联,必须加表别名前缀,如
SELECT u.id, o.status FROM users u JOIN orders o ON u.id = o.user_id - 对模糊字段名(如两个表都有
id)不加别名,MySQL 会报错:Column 'id' in field list is ambiguous
WHERE 条件里 NULL 不能用 = 判断,得用 IS NULL
新手常写 WHERE deleted_at = NULL,结果永远查不到数据——因为 SQL 中 NULL 参与任何比较运算都返回 UNKNOWN,不是 TRUE,所以被过滤掉。
正确写法只有两种:
-
WHERE deleted_at IS NULL(判断为空) -
WHERE deleted_at IS NOT NULL(判断非空)
注意:COALESCE(deleted_at, '1970-01-01') 或 IFNULL() 可临时转义,但会阻止索引使用,大数据量时慎用。
ORDER BY 后没加 LIMIT,分页查第10万条时性能会断崖下跌
写 SELECT * FROM logs ORDER BY id DESC 看似无害,但如果表有千万行,数据库必须把全部数据排序完才返回结果。线上服务可能直接超时或被 kill。
真实分页场景必须配合 LIMIT 和合理索引:
- 简单偏移分页:
SELECT id, title FROM articles ORDER BY created_at DESC LIMIT 20 OFFSET 10000—— 超过 1 万行后效率明显下降 - 更优做法是“游标分页”:记录上一页最后一条的
created_at值,下一页查WHERE created_at -
ORDER BY字段必须有索引,否则EXPLAIN会看到Using filesort
字符串模糊匹配用 LIKE 还是全文索引?取决于数据量和精度要求
LIKE '%关键词%' 在百万级数据上基本不可用——它无法使用 B-Tree 索引,只能全表扫描。而 LIKE '前缀%' 可走索引,但仅限左匹配。
选型参考:
- 小表(LIKE 'abc%' + 字段加索引
- 中大型表、需中间/右模糊:建
FULLTEXT索引,用MATCH(title) AGAINST('关键词' IN NATURAL LANGUAGE MODE) - 高并发、实时性要求高:别硬扛,导出到 Elasticsearch 或 Meilisearch
额外提醒:LIKE 中的下划线 _ 是单字符通配符,想查字面意义的下划线得转义,如 LIKE 'file\_%' ESCAPE '\',否则会误匹配。

















