1. LIMIT分页查询:你以为只取10条数据就很快?
分页查询是常见的场景,但当数据量巨大时,LIMIT 1000000, 10
这样的写法会让数据库从头扫描100万条记录,即使有索引也无济于事。优化方法是将上一页的最大值作为查询条件,例如:
SELECT *
FROM operation
WHERE type = 'SQLStats'
AND NAME = 'SlowLog'
AND create_time > '2017-03-16 14:00:00'
ORDER BY create_time LIMIT 10;
2. 隐式类型转换:索引失效的“隐形杀手”
当查询变量与字段类型不匹配时,数据库会进行隐式类型转换,导致索引失效。例如,字段bpn
定义为varchar(20)
,但查询时使用了数字14000000123
,MySQL会将字符串转换为数字再比较,索引失效。解决方法:确保查询变量与字段类型一致。
3. 关联更新/删除:子查询的“性能黑洞”
在MySQL中,关联更新或删除时,如果使用子查询,可能会导致循环嵌套查询,性能极差。例如:
UPDATE operation o SET status = 'applying'WHERE o.id IN
(SELECT id
FROM operation
WHERE group = 123);
优化方法是将子查询重写为JOIN
:
UPDATE operation o
JOIN
(SELECT id
FROM operation
WHERE group = 123) t
ON o.id = t.id SET status = 'applying';
4. 混合排序:索引无能为力的“硬伤”
MySQL无法利用索引进行混合排序(如ORDER BY a ASC, b DESC
),导致全表扫描。例如:
SELECT *
FROM my_order o
INNER JOIN my_appraise a
ON a.orderid = o.id
ORDER BY a.is_reply ASC, a.appraise_time DESC LIMIT 20;
优化方法是将查询拆分为UNION ALL
,分别排序后再合并:
(SELECT *
FROM my_order
WHERE is_reply = 0
ORDER BY appraise_time DESC LIMIT 20)UNION ALL
(SELECT *
FROM my_order
WHERE is_reply = 1
ORDER BY appraise_time DESC LIMIT 20)ORDER BY is_reply ASC, appraise_time DESC LIMIT 20;
5. EXISTS语句:嵌套子查询的“性能陷阱”
EXISTS
语句在MySQL中通常以嵌套子查询的方式执行,性能较差。例如:
SELECT *
FROM my_neighbor n
WHERE EXISTS
(SELECT 1
FROM message_info m
WHERE n.id = m.neighbor_id);
优化方法是将EXISTS
改为JOIN
:
SELECT *
FROM my_neighbor n
INNER JOIN message_info m
ON n.id = m.neighbor_id;
6. SELECT :不必要的“数据搬运工”
使用SELECT *
会查询所有列,增加磁盘I/O和网络传输负担。优化方法是只选择需要的列,例如:
SELECT id,
name,
create_time
FROM operation;
7. LIKE模糊匹配:通配符的“性能杀手”
LIKE '%text%'
这样的模糊匹配会导致全表扫描,性能极差。如果可能,尽量避免在开头使用通配符,例如:SELECT *
FROM table_name
WHERE column_name LIKE 'text%';
8. 游标:数据库的“性能黑洞”
游标会逐行处理数据,性能极差。如果需要进行多次查询,建议使用临时表或变量存储结果集,避免使用游标。
总结
SQL优化是一门艺术,更是一门科学。以上8种“坑”只是冰山一角,实际开发中还有更多细节需要注意。希望本文能帮助你避开这些“坑”,写出高性能的SQL语句。如果你有其他优化技巧,欢迎在评论区分享,如果觉得本文有用,别忘了点赞、转发哦!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
暂无评论内容