第六章 查询性能优化(上)

为什么查询会慢?

响应时间、扫描的行数、返回的行数,是衡量查询开销的三个指标(记录在慢日志中)

  • 查询了不需要的数据

    • 查询不需要的记录:比如查询了100条记录到应用,取其中的10条显示,最好的解决办法是加上LIMIT
    • 多表关联时返回全部列:应该只取需要的列,否则会返回所有关联表的所有记录
    • 总是取出全部列:比如SELECT * FROM xxx
    • 重复查询相同的数据:最好使用缓存
  • 扫描了额外的记录

    Explain语句中的type列的类型:

    • 全表扫描
    • 范围扫描
    • 唯一索引查询
    • 常数引用

    MySQL能够使用三种方式应用Where过滤条件,从好到坏依次为:

    • 在索引中使用Where条件来过滤不匹配的记录。这是在储存引擎层完成的
    • 使用覆盖索引扫描(Using index)来返回记录,直接从索引中过滤不需要的记录并返回命中的结果。这是在MySQL服务器层,但无须再回表查询记录
    • 从数据表中返回数据,然后过滤不满足条件的记录(Using where)。这是在服务器层完成,MySQL需要先从数据表读出记录然后过滤

怎么优化查询?

  • 可以将一个复杂查询改成多个简单查询

    因为MySQL从设计上让连接和断开都非常轻量级,加上现代网络速度非常快,多个小查询不成问题

  • 切分查询

    将一个大查询,切分成小查询,每个小查询的功能完全一样,每次只返回小部分查询结果。比如删除旧数据,如果用一个很大的语句一次性删除大量数据,会锁住很多数据、占满事务日志、耗尽系统资源、阻塞很多重要的小查询,可以切分成每次删除1000条,循环删除

  • 分解关联查询

    • 让缓存效率更高
    • 减少锁的竞争
    • 更容易拆分数据库,方便扩展
    • 提升查询效率,比如用IN()代替关联查询
    • 减少冗余记录的查询

一条查询是如何执行的?

1、客户端发送一条查询给服务器

MySQL客户端和服务器之间的通信协议是“半双工”的,同一时刻,要么是由服务器向客户端发送数据,要么是由客户端向服务器端发送数据,这两个动作不能同时发生

2、服务器先检查查询缓存,如果命中缓存,则立即返回储存在缓存中的结果。否则进入下一阶段

查询的状态

Sleep:线程正在等待客户端发送新的请求

Query:线程正在查询或者正在将结果发送给客户端

Locked:服务器层等待标锁

Analyzing and statistics:线程正在收集存储引擎的统计信息,并生成查询的执行计划

Copying to tmp table [on disk]:将结果拷贝到一个临时表,要么在做GROUP BY,要么文件排序、UNION表。如果后面还有“on disk”,表示MySQL正在将一个内存临时表放到磁盘上操作

Sorting result:线程正在对结果集进行排序

Sending data:线程正在传送数据

查询缓存

解析SQL语句之前,优先检查查询缓存,这是通过哈希查找实现的,如果命中缓存,那么在返回数据之前,还要检查一次用户权限

3、服务器端进行SQL解析、预处理,再由优化器生成对应的执行计划

MySQL通过关键字对SQL语句进行解析,生成“解析树”,验证是否关键字错误、语法错误、括号是否匹配,然后验证权限

4、MySQL根据优化器生成的执行计划,调用储存引擎的API来执行查询

5、将结果返回给客户端

查询优化器

一条查询可以有很多种执行方式,最后都返回相同的结果,优化器的作用就算找到这其中最好的执行计划

  • 导致优化器选择错误的执行计划的原因

    • 统计信息不准确

      MySQL依赖储存引擎提供的统计信息来评估成本,但是储存引擎提供的统计信息不一定准确,比如InnoDB因为有MVCC的架构,并不能维护一个数据表的行数精确统计信息

    • 执行计划中的成本估算不等同与实际的执行成本

      MySQL层面并不知道那些页面在内存中,哪些在磁盘上,所以查询实际执行过程中到底需要多少次物理IO是无法得知的

    • MySQL并不考虑其他并发执行的查询

    • MySQL不会考虑不受其控制的操作的成本

  • MySQL能够处理的优化类型

    • 重新定义关联表的顺序

    • 将外连接转化成内连接

    • 使用等价变换规则

      比如 5=5 AND a > 5 会改写成 a > 5

    • 优化COUNT()、MIN()和MAX()

      比如查找最小值,如果列在B-Tree中,那只要把最左的值拿出来就可以了;最大值把最右值拿出来就可以了

    • 预估并转化为常数表达式

      比如表达式转化为常数,有时候甚至一个查询也能转化为一个常数

    • 覆盖索引扫描

    • 子查询优化

    • 提前终止查询

      发现已经满足查询需求的时候,MySQL总是能够立刻终止查询。比如LIMIT

    • 等值传播

      如果两个列的值通过等式关联,那么MySQL能够把其中一个列的WHERE条件传递到另一个上。

    • 列表IN()的比较

      在很多数据系统中,IN()完全等同于多个OR条件的子句,因为这两者完全等价,但是在MySQL中不是这样的,MySQL将IN()列表中的数据先进行排序然后通过二分查找的方式确定列表中的值是否满足条件,这是一个O(logn)复杂度的查询,等级转换成OR是O(n),所以如果IN()列表中有大量取值的时候,MySQL的处理速度回更快

MySQL如何执行关联查询

按照where条件遍历第一个表,然后循环查询第二个表,使用on的筛选;
on的条件最好要是索引

返回结果给客户端

一旦服务器处理完最后一个关联表,开始生成第一条结果时,MySQL就可以开始向客户端逐步返回结果集了;比如Java的rs.next(),一条一条取,避免服务器内存压力过大;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 1. 为什么查询速度会慢 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间。如果要...
    李逍遥JK阅读 479评论 1 0
  • 国庆第二天,今天嗨翻模式的开启就等室友的同学来了再说吧,在这之前,先来一波笔记 查询真正重要的是响应时间,查询包含...
    小炼君阅读 1,696评论 0 50
  • MySQL性能优化的21个最佳实践 TechTarget中国原创内容,原文链接:http://www.search...
    学_无_止_境阅读 3,233评论 0 30
  • 如何设计最优的数据库表结构,如何建立最好的索引,以及如何扩展数据库的查询,这些对于高性能来说都是必不可少的。但是只...
    AI乔治阅读 998评论 0 24
  • --- layout: post title: "如果有人问你关系型数据库的原理,叫他看这篇文章(转)" date...
    蓝坠星阅读 777评论 0 3