Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

33 | MySQL调优之SQL语句:如何写出高性能SQL语句?

增加汇总统计
使用近似值
利用子查询优化分页查询
常用SQL调优方法
分析、定位慢SQL原因
避免慢SQL语句实现
生产环境数据增长后暴露性能问题
初期关注业务功能
活跃社区
稳定服务
卓越性能
开源免费
优化SELECT *
优化SELECT COUNT(*)
优化分页查询
通过Show Profile分析SQL执行性能
通过EXPLAIN分析SQL执行计划
不恰当的SQL语句
锁等待
无索引、索引失效导致慢查询
SQL语句
MySQL数据库
常用的SQL优化
优化SQL语句的步骤
慢SQL语句的几种常见诱因
性能调优
如何写出高性能SQL语句?

该思维导图由 AI 生成,仅供参考

你好,我是刘超。
从今天开始,我将带你一起学习 MySQL 的性能调优。MySQL 数据库是互联网公司使用最为频繁的数据库之一,不仅仅因为它开源免费,MySQL 卓越的性能、稳定的服务以及活跃的社区都成就了它的核心竞争力。
我们知道,应用服务与数据库的交互主要是通过 SQL 语句来实现的。在开发初期,我们更加关注的是使用 SQL 实现业务功能,然而系统上线后,随着生产环境数据的快速增长,之前写的很多 SQL 语句就开始暴露出性能问题。
在这个阶段中,我们应该尽量避免一些慢 SQL 语句的实现。但话说回来,SQL 语句慢的原因千千万,除了一些常规的慢 SQL 语句可以直接规避,其它的一味去规避也不是办法,我们还要学会如何去分析、定位到其根本原因,并总结一些常用的 SQL 调优方法,以备不时之需。
那么今天我们就重点看看慢 SQL 语句的几种常见诱因,从这点出发,找到最佳方法,开启高性能 SQL 语句的大门。

慢 SQL 语句的几种常见诱因

1. 无索引、索引失效导致慢查询

如果在一张几千万数据的表中以一个没有索引的列作为查询条件,大部分情况下查询会非常耗时,这种查询毫无疑问是一个慢 SQL 查询。所以对于大数据量的查询,我们需要建立适合的索引来优化查询。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了如何写出高性能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-06
    13
    97
  • QQ怪
    对staus和create_time建立联合索引

    作者回复: 对的,为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。 filesort是通过相应的排序算法将取得的数据在内存中进行排序,如果内存不够则会使用磁盘文件作为辅助。虽然在一些场景中,filesort并不是特别消耗性能,但是我们可以避免filesort就尽量避免。

    2019-08-06
    2
    17
  • Jian
    因为好久没有做SQL相关的开发了,所以开始没有特别明白【利用子查询优化分页查询】这里面的意思。我来说下自己的想法,请您检证。我看到您贴的截图中,优化后的sql语句,扫描的行数(rows列)分别是90409和10001,多余前一个较慢的查询,可见扫描行数,不是这个性能的主要原因。我推测这个是由于limit [m],n的实现方法导致的,即MySql会把m+n的数据都取出来,然后返回n个数据给用户。如果用第二种SQL语句,子查询只是获得一个id,虽然扫描了很多行,但都是在索引上进行的,切不需要回表获取内容。外查询是根据id获取数据20条内容,速度自然就会快了。我认为这里性能提高的原因还是居于索引的恰当使用。

    作者回复: 可以这么理解

    2019-08-12
    4
    16
  • 尔冬橙
    老师,分页查询优化那一块,单从扫描函数看,采用子查询和不采用子查询扫描总行数是差不多的,而不采用子查询,第一个主查询就是返回10020条记录,采用子查询只返回20条记录?我理解是结果集有多少行就是返回多少记录。是因为子查询不返回记录么,它不也扫描了10000行么?

    作者回复: 数据库需要查询 10020 条记录,最后返回 20 条记录,也就是说将会有 10000 条记录被查询出来没有被使用到。子查询是select id from `demo`.`order` order by order_no limit 10000, 1虽然会扫描10000条数据,但并不会查询出10000条数据,最终查询出来的是一个id值,而这个id值又是主键。

    2020-02-26
    13
  • 课后思考及问题 1:按照效率排序的话,count(字段)<count(主键 id)<count(1)≈count(*),所以我建议你,尽量使用 count(*)。——MySQL,丁奇老师的结论 如果对一张大表经常做 SELECT COUNT(*) 操作,这肯定是不明智的。——刘老师的结论 同样的问题,不同的老师给出了截然相反的结论,我希望有一天两位老师可以讨论一下为什么? 刘老师具体没讲COUNT(*)的原理,我倾向于认为丁奇老师的结论是正确的。

    作者回复: 我与丁奇结论没有相反,丁奇是建议你在这些count类型中选择使用count(*),而我是建议不要在大表中做count(*)。丁奇老师讲解了COUNT(*)的原理,我相信他也会建议你不要在一个大表中频繁COUNT(*)。

    2019-09-14
    4
    8
  • 迎风劲草
    创建 status create_time order_no 联合索引,避免回表

    作者回复: 建立联合索引没错,还有就是避免文件排序的问题。

    2019-08-06
    3
    5
  • mumu
    select * 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-04
    2
    4
  • 张三丰
    就算使用了联合索引,也避免不了排序吧,因为题目要求的是降序,联合索引是保证第一个索引有序的前提下再保证第二个索引有序,那么这个有序是升序,如果没记错的话。

    作者回复: 只要有序的,就不会再重复排序了,只是一个升降序的问题了

    2019-10-04
    2
    4
  • 尔冬橙
    为什么分页查询优化那块,主查询扫描这么多行?

    作者回复: 使用limit 10000,1,所以需要顺序扫描到10001行,所以我们尽量使用主键递增的方式,直接将主查询换成select * from `demo`.`order` where id> 10000 limit 20,避免扫描带来的性能问题。

    2019-09-26
    3
  • Geek_002ff7
    真实情况一般不会在status上单独建索引,因为status大部分都是重复值,数据库一般走全表扫描了,感觉漏讲了索引失效的情况

    作者回复: 下一讲则会讲到

    2019-08-09
    3
收起评论
显示
设置
留言
45
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部