高性能mysql 第六章查询性能优化 总结(上)查询的执行过程
6 查询性能优化
6.1为什么查询会变慢
这里说明了的查询执行周期,从客户端到服务器端,服务器端解析,优化器生成执行计划,执行(可以细分,大体过程可以通过show profile查看),从服务器端返回客户端结果。
而执行部分作为最重要的一环,需要做的事情比较多,而不合适的query往往让执行过程做了不必要的操作,或者不能使用更优秀的底层数据结构,从而用时更久。
6.2慢查询基础:优化数据访问
访问数据量多大,超过实际所需是慢查询的一个原因。导致这种情况的原因大致有两个
1.应用程序向mysql服务要求的了超过需要的,或重复的数据,比如select * 。
2.mysql服务器执行过程中访问了超过需要的数据。
我们先来看第一种原因
6.2.1向数据库请求了超过需要的数据
1.请求了超过需要的行,如没有使用limit,请求了100行数据,但是只使用了10行。
2.使用select * 返回了不需要的列数据,尤其是多表关联查询是情况更突出,应该做的是只返回我们需要的列。
3.客户端如果使用了缓存,并且该部分缓存被接下来的数据需求命中,那么就没有必要再向服务器发送数据请求。
6.2.2mysql扫描了额外的纪录
慢查询日志中的三个衡量查询开销的指标:1.响应时间,2。扫描行数,3.返回行数
1.响应时间
响应时间包括服务时间与排队时间。
响应时间在不同的服务器环境,应用环境下都会不同。文中提到使用‘快速上限法’(中文版译名):通过query的执行计划,计算需要的顺序io与随机io次数,再结合当前环境下一次io的时间。最后做一次加总可以获得一个‘参考值‘。(可以看出来,这样的一种方法实操性并不强,因为并不是每一个query我们都能相对准确的估算io次数,不同服务器环境下,甚至统一服务器的不同时间,io的效率也会不同。 不过这里我们可以看出来,io是执行过程中相对比较耗时的一步)
2.扫描行数与返回行数
扫描行数与返回行数单独都是不能体现出任何query的效率的,只有两者的比值才能说明该query筛选数据的能力。
3.扫描行数与访问类型
explain 中的type列列出了访问类型:全表扫;索引扫描;范围扫描;单值查询
6.3重构查询的方式
6.3.1一个复杂的查询还是多个简单的查询
由于mysql的网络协议是‘半双工’的,连接断开的花费并不大,所以很多时候分解查询是优化的sql的一个有效方式。
6.3.2切分查询
切分查询是指对大的查询采取分而治之的策略,分时段分但服务器端的压力。但次执行分段的sql都是一样的,只是通过do_query()返回的数据与limit实现对数据条目的分批处理。
6.3.3分解关联查询
将关联查询分解成多个sql步骤。
这样做是减小事务的粒度,能够缓解锁的争用,也能让缓存的数据更加模块化,易于使用缓存。
6.4查询的执行步骤
客户端请求数据-->服务器端查询缓存,命中返回,未命中-->mysql解析sql,预编译,生成执行计划-->调用数据库引擎api执行sql-->返回结果到客户端
6.4.1mysql通信协议
‘半双工’。即同一时间,只有一方在发送数据,只有在接受完对方发送的数据,才可以向对方发出响应。
这里提到了客户端获取数据的两种方式,在c#一种是dateset,即一次性返回数据,在客户端保存数据快照(缓存),一种dateread是保持客户端与服务器端的连接,客户端随时查询数据。--不同的语言提供了不同的调用方式。
查询状态
指的是查询的进程的执行状态:需要注意的是sort result对结果集排序;sanding date表示自生成结果集或者在向客户端返回数据。
6.4.2查询缓存
就是查询步骤中的第二步查询的结构。第七章中有介绍。
6.4.3查询优化
即是查询步骤中的第三步
1.语言解析器与预处理器
解析器对语法进行检查,预处理器检查语义并检查用户是否有权限。
2.查询优化器
优化器对预处理器生成的预处理树进行执行计划的测算,计算各种执行计划的花费(有前面的知识我们知道,这里的花费往往指的是查询需要访问的数据页的多少)
可以明白:优化器对成本的测算并不是啊完全准确的,但是对于大多数sql,io都是它的执行瓶颈所在。
注意优化器并不会考虑缓存(有缓存的话不应该第二步就命中,返回给客户端了吗。
优化有静态优化与动态优化的区分,考虑到第七章查询缓存部分与存储过程的描述,我在考虑mysql是否保存执行计划呢?如何保存sql的执行计划的呢?静态动态优化时二选一还是并存呢?
书中列出了10多中优化器能够优化的查询,我不在一一列举。
- 数据索引的统计信息
Myisam引擎保存了count,而innodb只能提供估算值(innodb的数据与索引是纠缠的,插入删除修改还可能导致页分裂,页合并等问题,所以保存一个count之类的统计值维护不易)
4.关联查询的执行
Mysql的关联查询可以看做一个双循环或者多循环,只有两个表的关联查询,外侧循环的表叫外表,内侧循环的表叫内表。可以知道内侧循环的查询次数是远多于外侧的,所以内表非常需要一个合适的索引。
5.关联查询优化器
但是内外表常常不是我们可以决定的,mysql优化器会在其中起作用,优化器会建立一颗深度优先树,通过不同的组合得出花费最少的执行计划。不过在关联的表n过多时执行计划树的颗数会指数上升,n超过optimizer_search_depth就不再使用穷举的方式了,而是使用别的搜索方式获取最优执行计划。
上一段中mysql对关联查询的执行方式是嵌套循环,执行计划表现为一颗深度优先树。
- 排序优化
第三章中介绍了索引排序,这里介绍filesort。
Filesort文件排序,filesort并不总是要用到磁盘,当数据量较小时可以再内存中进行。
数据量是否大于文件缓冲区是两者的分水岭。当使用磁盘排序是相当于外排序。
Mysql filesort排序策略
两次读取数据(旧版):只使用行指针与排序字段做排序,这样排序结果需要通过行指针才能读取到全部数据,由于是随机io,io效率低。
单次读取数据(新版):先读取所需要的列,然后在根据给定列进行排序。
两个各有优劣,这个讨论我们放在第8章中
5.6版本在这里做出了改进,当使用limit时,mysql不再对所有结果排序,而是仅对需要的数据排序。
6.4.4查询执行引擎
Mysql的执行计划是一个数据结构,执行该执行计划时,需要调用存储引擎是响应的‘handler api’实现。如果是所有存储过程共有的特性,一般是服务器层实现的,如日期函数,视图,触发器。
6.4.5返回数据
Mysql执行sql过程中,开始生成第一条结果时就开始返回数据,这样是的服务器不需要保存大量的结果。(往后看可以发现union会到这个需要新建一个临时表来保存数据,前部union段执行完成才能返回数据)
高性能mysql 第六章查询性能优化 总结(上)查询的执行过程的更多相关文章
- mysql笔记03 查询性能优化
查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...
- Sql Server查询性能优化之走出索引的误区
据了解绝大多数开发人员对于索引的理解都是一知半解,局限于大多数日常工作没有机会.也什么没有必要去关心.了解索引,实在哪天某个查询太慢了找到查询条件建个索引就ok,哪天又有个查询慢了,再建立个索引就是, ...
- MySQL性能调优与架构设计——第9章 MySQL数据库Schema设计的性能优化
第9章 MySQL数据库Schema设计的性能优化 前言: 很多人都认为性能是在通过编写代码(程序代码或者是数据库代码)的过程中优化出来的,其实这是一个非常大的误区.真正影响性能最大的部分是在设计中就 ...
- MySQL查询性能优化(精)
MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...
- 170727、MySQL查询性能优化
MySQL查询性能优化 MySQL查询性能的优化涉及多个方面,其中包括库表结构.建立合理的索引.设计合理的查询.库表结构包括如何设计表之间的关联.表字段的数据类型等.这需要依据具体的场景进行设计.如下 ...
- 到底该不该使用存储过程 MySQL查询性能优化一则
到底该不该使用存储过程 看到<阿里巴巴java编码规范>有这样一条 关于这条规范,我说说我个人的看法 用不用存储过程要视所使用的数据库和业务场景而定的,不能因为阿里巴巴的技术牛逼,就视 ...
- MySQL查询性能优化七种武器之索引下推
前面已经讲了MySQL的其他查询性能优化方式,没看过可以去了解一下: MySQL查询性能优化七种武器之索引潜水 MySQL查询性能优化七种武器之链路追踪 今天要讲的是MySQL的另一种查询性能优化方式 ...
- Mysql优化系列之查询性能优化前篇1
前言 这是优化系列的最后一篇的第1小篇,我们其实可以直接从sql怎么写讲起,why not?但是我还是决定花2个篇幅 问一些问题,带着几个问题循序渐进的往下走. 一个sql语句是怎么被执行的? sql ...
- Mysql数据库调优和性能优化
1. 简介 在Web应用程序体系架构中,数据持久层(通常是一个关系数据库)是关键的核心部分,它对系统的性能有非常重要的影响.MySQL是目前使用最多的开源数据库,但是mysql数据库的默认设置性能非常 ...
随机推荐
- linux-Centos7安装python3并与python2共存
1.查看是否已经安装Python CentOS 7.2 默认安装了python2.7.5 因为一些命令要用它比如yum 它使用的是python2.7.5. 使用 python -V 命令查看一下是否安 ...
- 安装tifffile
python的opencv和PIL不能很好地处理tiff图像,所以我就转用tifffile 但是tifffile也装了很近,因为我是远控别人的电脑,所以看不太清报错,就自己瞎猜,不过还是装好了 首先去 ...
- 学生信息管理系统(C语言)
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct student ...
- linux下配置mysql 与错误解决
1.下载mysql wget https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.11-el7-x86_64.tar.gz 2.检查linux是否 ...
- 在数据库中sql查询很快,但在程序中查询较慢的解决方法
在写java的时候,有一个方法查询速度比其他方法慢很多,但在数据库查询很快,原来是因为程序中使用参数化查询时参数类型错误的原因 select * from TransactionNo, fmis_Ac ...
- cocos2d-x学习笔记(斗地主代码)
满足百度百科上的出牌规则,电脑可以随着玩家出牌. 百度网盘地址:链接: https://pan.baidu.com/s/1eRLpvJ8 提取密码: tf8w
- Java基础-访问修饰符
访问修饰符 default (即缺省,什么也不写): 在同一包内可见,不使用任何修饰符.使用对象:类.接口.变量.方法. private : 在同一类内可见.使用对象:变量.方法. 注意:不能修饰类( ...
- Msfvenom学习总结
1. –p (- -payload-options) 添加载荷payload. 载荷这个东西比较多,这个软件就是根据对应的载荷payload生成对应平台下的后门,所以只有选对payload,再填 ...
- linux下的$0-n作用
电面的时候回答上来一部分了....呵呵......总结一下!!! $0 Shell本身的文件名 $1-$n 添加到Shell的各参数值.$1是第1参数.$2是第2参数… $$ Shell本身的PID( ...
- css 长用点
功能 : font-size: 0; 去除图片之间空白空隙