-- 正确示例:使用WHERE条件代替大偏移量 SELECT*FROM users WHERE id >100000ORDERBY id LIMIT 10;
-- 或者使用游标分页 SELECT*FROM users WHERE id > :last_id ORDERBY id LIMIT 10;
3. 去重操作优化
1 2 3 4 5 6 7 8 9 10 11
-- 避免使用DISTINCT,考虑使用GROUP BY -- 如果可能,通过业务逻辑避免重复数据
-- 示例:统计不同用户的订单数 -- 使用GROUP BY代替DISTINCT SELECT user_id, COUNT(*) as order_count FROM orders GROUPBY user_id;
-- 而不是 SELECTDISTINCT user_id FROM orders; -- 只能获取用户ID,信息有限
(三)优化JOIN操作
1. 小表驱动大表原则
1 2 3 4 5 6 7 8 9
-- 正确示例:小表(categories)驱动大表(products) SELECT p.name, c.category_name FROM categories c -- 小表在前(假设只有几十个分类) JOIN products p ON c.id = p.category_id -- 大表在后(假设有数万个产品) WHERE c.status ='active';
-- 确保JOIN条件字段上有索引 -- 在products表的category_id字段上创建索引 CREATE INDEX idx_products_category_id ON products(category_id);
2. JOIN代替子查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-- 错误示例:使用子查询,可能产生临时表 SELECT*FROM users WHERE id IN ( SELECT user_id FROM orders WHERE total >1000 );
-- 正确示例:使用JOIN,通常性能更好 SELECTDISTINCT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.total >1000;
-- 或者使用EXISTS(适用于只需要判断存在性的场景) SELECT*FROM users u WHEREEXISTS ( SELECT1FROM orders o WHERE o.user_id = u.id AND o.total >1000 );
(四)批量操作优化
1. 批量插入优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-- 错误示例:逐条插入,事务开销大 INSERT INTO users (name, email) VALUES ('User1', 'user1@example.com'); INSERT INTO users (name, email) VALUES ('User2', 'user2@example.com'); INSERT INTO users (name, email) VALUES ('User3', 'user3@example.com');
-- 大批量数据导入:使用LOAD DATA INFILE LOAD DATA INFILE '/path/to/users.csv' INTOTABLE users FIELDS TERMINATED BY',' LINES TERMINATED BY'\n' (name, email);
2. 批量更新优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-- 使用事务包裹批量操作 START TRANSACTION;
UPDATE users SET status ='active'WHERE last_login >'2023-01-01'; UPDATE users SET status ='inactive'WHERE last_login <'2022-01-01'; DELETEFROM users WHERE status ='deleted'AND created_at <'2020-01-01';
COMMIT;
-- 使用CASE WHEN进行条件批量更新 UPDATE users SET status =CASE WHEN last_login >'2023-01-01'THEN'active' WHEN last_login <'2022-01-01'THEN'inactive' ELSE status END WHERE last_login ISNOT NULL;