后端存储实战课
李玥
京东零售计算存储平台部资深架构师
立即订阅
3274 人已学习
课程目录
已更新 15 讲 / 共 26 讲
0/4登录后,你可以任选4讲全文学习。
课前必读 (2讲)
开篇词 | 从今天起,换种方式学存储
免费
课前加餐 | 电商系统是如何设计的?
创业篇 (7讲)
01 | 创建和更新订单时,如何保证数据准确无误?
02 | 流量大、数据多的商品详情页系统该如何设计?
03 | 复杂而又重要的购物车系统,应该如何设计?
04 | 事务:账户余额总是对不上账,怎么办?
05 | 分布式事务:如何保证多个系统间的数据是一致的?
06 | 如何用Elasticsearch构建商品搜索系统?
07|MySQL HA:如何将“删库跑路”的损失降到最低?
高速增长篇 (6讲)
08 | 一个几乎每个系统必踩的坑儿:访问数据库超时
09 | 怎么能避免写出慢SQL?
10 | 走进黑盒:SQL是如何在数据库中执行的?
11 | MySQL如何应对高并发(一):使用缓存保护MySQL
12 | MySQL如何应对高并发(二):读写分离
13 | MySQL主从数据库同步是如何实现的?
后端存储实战课
登录|注册

09 | 怎么能避免写出慢SQL?

李玥 2020-03-17
你好,我是李玥。
通过上节课的案例,我们知道,一个慢 SQL 就可以直接让 MySQL 瘫痪。今天这节课,我们一起看一下,怎么才能避免写出危害数据库的慢 SQL。
所谓慢 SQL,就是执行特别慢的 SQL 语句。什么样的 SQL 语句是慢 SQL?多慢才算是慢 SQL?并没有一个非常明确的标准或者说是界限。但并不是说,我们就很难区分正常的 SQL 和慢 SQL,在大多数实际的系统中,慢 SQL 消耗掉的数据库资源,往往是正常 SQL 的几倍、几十倍甚至几百倍,所以还是非常容易区分的。
但问题是,我们不能等着系统上线,慢 SQL 吃光数据库资源之后,再找出慢 SQL 来改进,那样就晚了。那么,怎样才能在开发阶段尽量避免写出慢 SQL 呢?

定量认识 MySQL

我们回顾一下上节课的案例,那个系统第一次全站宕机发生在圣诞节平安夜,故障之前的一段时间,系统并没有更新过版本,这个时候,其实慢 SQL 已经存在了,直到平安夜那天,访问量的峰值比平时增加一些,正是增加的这部分访问量,引发了数据库的雪崩。
这说明,慢 SQL 对数据库的影响,是一个量变到质变的过程,对“量”的把握,就很重要。作为一个合格的程序员,你需要对数据库的能力,有一个定量的认识。
影响 MySQL 处理能力的因素很多,比如:服务器的配置、数据库中的数据量大小、MySQL 的一些参数配置、数据库的繁忙程度等等。但是,通常情况下,这些因素对于 MySQL 性能和处理能力影响范围,大概在几倍的性能差距。所以,我们不需要精确的性能数据,只要掌握一个大致的量级,就足够指导我们的开发工作了。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《后端存储实战课》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(23)

  • 冯玉鹏
    innodb 的索引是用索引关联列以b+树的形式 管理,其中主键索性和数据的物理顺序一致,也叫聚集索引。非主键索引实际上是指向主键索引。
    文末的问题对 department_code 列 left 运算后,MySQL 认为运算后的结果不可与原数据列内容匹配,故采用全表扫描, 而第二个语句like '00028%' 可以使用到索引 是因为索引的最左匹配选择,如果%在前面也将无法使用索引。PS:在这里MySQL的查询优化器在使用了left函数无法匹配索引可以认为有偷懒的嫌疑,哈哈~ 类似的场景还有 where 列 +1 = val 查询优化器也完全可以改写成 where 列=val - 1。

    作者回复: 👍👍👍

    2020-03-17
    2
    11
  • 小袁
    简单来说,要写成 "索引 列 = 计算表达式"这种形式,养成这个习惯
    2020-03-17
    2
  • image
    Btree索引树只能根据索引值进行范围查找,而无法进行函数运算后查找
    2020-03-21
    1
  • 活到天年
    是因为等号的左边使用了函数,如果等号左边使用了函数,则会导致全表扫描,但是如果可以建立函数索引的话,也可以提高查询效率。
    2020-03-20
    1
  • 一步
    作为一个合格的程序员,要对数据库的处理能力,有个定量的认知。 说的很对,认同
    有个问题就是,有没有一个指标可以知道MySQL每秒钟执行的SQL数量?
    2020-03-17
    1
    1
  • 攻城拔寨
    索引使用函数会让索引失效,因为必须拿所有索引去计算才能得到结果
    2020-03-17
    1
  • 火车日记
    where中列使用了函数,优化器无法用到索引
    2020-03-17
    1
  • 饼子
    因为where条件使用了函数运算,那么只有扫描每一行才能确定函数执行后的值与判断是否一致
    2020-03-25
  • 特种流氓
    老师 能否在mysql中做设置 超时的sql查询自动停止执行
    2020-03-25
  • leslie
    原因很简单:函数破坏了索引,其实这种写法基本上都会在程序端禁止的;code review这关过不去的,直接发回开发-重写。like 语句其实用到了mysql 5.7所引用的特性 分列,问题就这么简单。
    2020-03-25
  • fgdgtz
    你好老师,我想问问如果是 order by 多个字段排序的执行流程是什么样的呢?
    比如 有40000行 order by a desc,b desc limit 1000 ,a字段有索引,b字段无索引,a字段保存的是时间戳,有少部分时间戳是同样的,此时explain 会有 Using filesort,这样放入sort_buffer 是40000行 还是 大于1000行而小于40000行呢?或是扫描了多少行?

    作者回复: 你可以把SQL和执行计划贴出来我们一起讨论。

    2020-03-21
    1
  • Regis
    后台实际开发中,使用ORM的框架的情况是不是很多?如果使用ORM框架,SQL的写法就不可控了。实际开发中是使用ORM框架好还是直接书写SQL好?还是两种都会存在?一些复杂的查询使用框架查询感觉很痛苦

    作者回复: 我的建议是,在线交易类系统(OLTP,大部分服务业务的CRUD类系统)使用ORM框架。

    分析类系统(OLAP,各种分析和报表类系统)直接写SQL。

    2020-03-18
  • 隗功庆
    运算不能使用索引
    2020-03-17
  • 肥low
    因为第一个用到了函数 如果在建立索引的时候就left 在SQL中不显式的left就能用到了
    2020-03-17
  • 刘楠
    LEFT()函数是一个字符串函数,它返回具有指定长度的字符串的左边部分。

      LEFT(Str,length);

      接收两个参数:

        str:一个字符串;

        length:想要截取的长度,是一个正整数;
    left函数,会扫描所有的行,并试图找到所有能与匹配的记录,是值班表扫描
    2020-03-17
  • 夜空中最亮的星(华仔)
    运算不能使用索引
    2020-03-17
  • 0x12FD16B
    MySQL 执行器去执行查询语句时会先去查询所有的 user 信息,然后对 department_code列执行函数,再和 00028 比较。
    2020-03-17
  • 滴流乱转小胖子
    使用left(department_code, 5)函数对department_code列所有值,进行了操作,只能进行全表扫描。 对不对老师?
    2020-03-17
  • 撒旦的堕落
    应该是where条件后使用了函数导致无法使用索引
    2020-03-17
  • 饭团
    因为where条件左值使用了函数!
    2020-03-17
收起评论
23
返回
顶部