33 | MySQL调优之SQL语句:如何写出高性能SQL语句?
该思维导图由 AI 生成,仅供参考
慢 SQL 语句的几种常见诱因
1. 无索引、索引失效导致慢查询
- 深入了解
- 翻译
- 解释
- 总结
本文介绍了如何写出高性能SQL语句的方法。首先,作者指出了慢SQL语句的几种常见诱因,包括无索引、索引失效导致慢查询、锁等待以及不恰当的SQL语句。然后,作者提出了优化SQL语句的步骤,包括通过EXPLAIN分析SQL执行计划和通过Show Profile分析SQL执行性能。最后,文章总结了常用的SQL优化方法,指出通过一些方法和技巧来优化SQL的实现可以将性能提升到另一个数量级。整体而言,本文深入浅出地介绍了SQL性能调优的相关知识,对于需要提升数据库性能的读者具有一定的参考价值。 文章中提到了几种SQL优化方法,包括优化分页查询、优化SELECT COUNT(*)、优化SELECT *。在优化分页查询方面,通过使用子查询和索引覆盖扫描来提高分页查询的效率;在优化SELECT COUNT(*)方面,建议使用近似值或增加汇总统计来提升COUNT()函数的性能;在优化SELECT *方面,强调了避免不必要的查询和利用合适的索引来提高查询效率。此外,还提到了如何通过慢SQL配置项和数据库连接池中间件来分析和监控SQL性能。 总的来说,本文通过具体的案例和技术原理,为读者提供了一些实用的SQL性能优化方法,帮助他们在实际工作中写出高性能的SQL语句。
《Java 性能调优实战》,新⼈⾸单¥59
全部留言(45)
- 最新
- 精选
- 张学磊status和create_time单独建索引,在查询时只会遍历status索引对数据进行过滤,不会用到create_time列索引,将符合条件的数据返回到server层,在server对数据通过快排算法进行排序,Extra列会出现file sort;应该利用索引的有序性,在status和create_time列建立联合索引,这样根据status过滤后的数据就是按照create_time排好序的,避免在server层排序
作者回复: 非常准确!
2019-08-061397 - QQ怪对staus和create_time建立联合索引
作者回复: 对的,为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。 filesort是通过相应的排序算法将取得的数据在内存中进行排序,如果内存不够则会使用磁盘文件作为辅助。虽然在一些场景中,filesort并不是特别消耗性能,但是我们可以避免filesort就尽量避免。
2019-08-06217 - Jian因为好久没有做SQL相关的开发了,所以开始没有特别明白【利用子查询优化分页查询】这里面的意思。我来说下自己的想法,请您检证。我看到您贴的截图中,优化后的sql语句,扫描的行数(rows列)分别是90409和10001,多余前一个较慢的查询,可见扫描行数,不是这个性能的主要原因。我推测这个是由于limit [m],n的实现方法导致的,即MySql会把m+n的数据都取出来,然后返回n个数据给用户。如果用第二种SQL语句,子查询只是获得一个id,虽然扫描了很多行,但都是在索引上进行的,切不需要回表获取内容。外查询是根据id获取数据20条内容,速度自然就会快了。我认为这里性能提高的原因还是居于索引的恰当使用。
作者回复: 可以这么理解
2019-08-12416 - 尔冬橙老师,分页查询优化那一块,单从扫描函数看,采用子查询和不采用子查询扫描总行数是差不多的,而不采用子查询,第一个主查询就是返回10020条记录,采用子查询只返回20条记录?我理解是结果集有多少行就是返回多少记录。是因为子查询不返回记录么,它不也扫描了10000行么?
作者回复: 数据库需要查询 10020 条记录,最后返回 20 条记录,也就是说将会有 10000 条记录被查询出来没有被使用到。子查询是select id from `demo`.`order` order by order_no limit 10000, 1虽然会扫描10000条数据,但并不会查询出10000条数据,最终查询出来的是一个id值,而这个id值又是主键。
2020-02-2613 - 钱课后思考及问题 1:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。——MySQL,丁奇老师的结论 如果对一张大表经常做 SELECT COUNT(*) 操作,这肯定是不明智的。——刘老师的结论 同样的问题,不同的老师给出了截然相反的结论,我希望有一天两位老师可以讨论一下为什么? 刘老师具体没讲COUNT(*)的原理,我倾向于认为丁奇老师的结论是正确的。
作者回复: 我与丁奇结论没有相反,丁奇是建议你在这些count类型中选择使用count(*),而我是建议不要在大表中做count(*)。丁奇老师讲解了COUNT(*)的原理,我相信他也会建议你不要在一个大表中频繁COUNT(*)。
2019-09-1448 - 迎风劲草创建 status create_time order_no 联合索引,避免回表
作者回复: 建立联合索引没错,还有就是避免文件排序的问题。
2019-08-0635 - mumuselect * from `demo`.`order` where id> (select id from `demo`.`order` order by order_no limit 10000, 1) limit 20;,老师您好,我不懂这样写为什么是正确的,为什么id>子查询结果的20条就是按order_no排序所需的20条?
作者回复: 这里我们就默认orderno是递增的,而且是随着id自增长递增
2019-11-0424 - 张三丰就算使用了联合索引,也避免不了排序吧,因为题目要求的是降序,联合索引是保证第一个索引有序的前提下再保证第二个索引有序,那么这个有序是升序,如果没记错的话。
作者回复: 只要有序的,就不会再重复排序了,只是一个升降序的问题了
2019-10-0424 - 尔冬橙为什么分页查询优化那块,主查询扫描这么多行?
作者回复: 使用limit 10000,1,所以需要顺序扫描到10001行,所以我们尽量使用主键递增的方式,直接将主查询换成select * from `demo`.`order` where id> 10000 limit 20,避免扫描带来的性能问题。
2019-09-263 - Geek_002ff7真实情况一般不会在status上单独建索引,因为status大部分都是重复值,数据库一般走全表扫描了,感觉漏讲了索引失效的情况
作者回复: 下一讲则会讲到
2019-08-093