避免全表扫描,善用索引
很多人写查询时习惯直接写 SELECT * FROM users WHERE name = '张三',看起来没问题,但如果 users 表有上百万条数据,name 字段又没加索引,这条查询就会触发全表扫描,速度慢得像老牛拉车。
解决办法是给常用查询字段加索引。比如 name、created_time 这类经常用于筛选的字段,加上索引后查询速度能从几秒降到毫秒级。但注意别滥用,索引会拖慢写入速度,尤其是频繁插入更新的表。
CREATE INDEX idx_user_name ON users(name);只查需要的字段
别动不动就 SELECT *,尤其在关联多表时。假设你只需要用户姓名和邮箱,却把整张表都查出来,不仅浪费内存,网络传输也更慢。实际开发中见过有人在手机端列表页查了几十个字段,页面卡得用户以为应用崩了。
明确指定字段名,减少数据量:
SELECT name, email FROM users WHERE status = 1;合理使用 JOIN 和子查询
多表关联时,JOIN 比子查询更高效的情况很多。比如要查订单金额大于平均值的用户信息,用 JOIN 能让数据库优化器更好规划执行路径。
SELECT u.name, o.amount FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > (SELECT AVG(amount) FROM orders);但嵌套太深的子查询容易让数据库“迷路”,尽量控制在两层以内。如果逻辑复杂,可以考虑拆成临时表或程序里分步处理。
利用 LIMIT 控制结果集大小
做分页时别用 OFFSET 跳过大量数据。比如 LIMIT 10000, 20,数据库其实还是扫了前一万条。对于大表,这种写法越来越慢。可以用主键范围替代:
SELECT id, name FROM users WHERE id > 10000 LIMIT 20;前提是按 ID 顺序翻页,用户体验一样,性能却提升明显。
避免在 WHERE 条件中对字段做计算
像 WHERE YEAR(create_time) = 2024 这种写法,即使 create_time 有索引也会失效。因为数据库得先算出每行的年份,再比对,等于白建了索引。
改成范围查询就能命中索引:
WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';批量操作尽量合并
程序里循环执行单条 INSERT 或 UPDATE 是性能杀手。每次都要走网络、解析、事务开销。如果有几百条数据要插,合并成一条批量语句快得多。
INSERT INTO logs (type, message) VALUES ('login', '成功'), ('logout', '退出'), ('error', '超时');有些 ORM 默认一条条执行,记得手动开启批处理模式。