mysql explain和profiling
语法:explain select ....
ICP(index condition pushdown)是mysql利用索引(二级索引)元组和筛字段在索引中的where条件从表中提取数据记录的一种优化操作。ICP的思想是:存储引擎在访问索引的时候检查筛选字段在索引中的where条件(pushed index condition,推送的索引条件),如果索引元组中的数据不满足推送的索引条件,那么就过滤掉该条数据记录。ICP(优化器)尽可能的把index condition的处理从server层下推到storage engine层。storage engine使用索引过过滤不相关的数据,仅返回符合index condition条件的数据给server层。也是说数据过滤尽可能在storage engine层进行,而不是返回所有数据给server层,然后后再根据where条件进行过滤。使用ICP(mysql 5.6版本以前)和没有使用ICP的数据访问和提取过程如下(插图来在MariaDB Blog):
优化器没有使用ICP时,数据访问和提取的过程如下:
1) 当storage engine读取下一行时,首先读取索引元组(index tuple),然后使用索引元组在基表中(base table)定位和读取整行数据。
2) sever层评估where条件,如果该行数据满足where条件则使用,否则丢弃。
3) 执行1),直到最后一行数据。

优化器使用ICP时,server层将会把能够通过使用索引进行评估的where条件下推到storage engine层。数据访问和提取过程如下:
1) storage engine从索引中读取下一条索引元组。
2) storage engine使用索引元组评估下推的索引条件。如果没有满足wehere条件,storage engine将会处理下一条索引元组(回到上一步)。只有当索引元组满足下推的索引条件的时候,才会继续去基表中读取数据。
3) 如果满足下推的索引条件,storage engine通过索引元组定位基表的行和读取整行数据并返回给server层。
4) server层评估没有被下推到storage engine层的where条件,如果该行数据满足where条件则使用,否则丢弃。

而使用ICP时,如果where条件的一部分能够通过使用索引中的字段进行评估,那么mysql server把这部分where条件下推到storage engine(存储引擎层)。存储引擎通过索引元组的索引列数据过滤不满足下推索引条件的数据行。
索引条件下推的意思就是筛选字段在索引中的where条件从server层下推到storage engine层,这样可以在存储引擎层过滤数据。由此可见,ICP可以减少存储引擎访问基表的次数和mysql server访问存储引擎的次数。
注意一下ICP的使用条件:
- 只能用于二级索引(secondary index)。
- explain显示的执行计划中type值(join 类型)为range、 ref、 eq_ref或者ref_or_null。且查询需要访问表的整行数据,即不能直接通过二级索引的元组数据获得查询结果(索引覆盖)。
- ICP可以用于MyISAM和InnnoDB存储引擎,不支持分区表(5.7将会解决这个问题)。
ICP的开启优化功能与关闭
MySQL5.6可以通过设置optimizer_switch([global|session],dynamic)变量开启或者关闭index_condition_push优化功能,默认开启。
mysql > set optimizer_switch=’index_condition_pushdown=on|off’
用explain查看执行计划时,如果执行计划中的Extra信息为“using index condition”,表示优化器使用的index condition pushdown。
在mysql5.6以前,还没有采用ICP这种查询优化,where查询条件中的索引条件在某些情况下没有充分利用索引过滤数据。假设一个组合索引(多列索引)K包含(c1,c2,…,cn)n个列,如果在c1上存在范围扫描的where条件,那么剩余的c2,…,cn这n-1个上索引都无法用来提取和过滤数据(不管不管是唯一查找还是范围查找),索引记录没有被充分利用。即组合索引前面字段上存在范围查询,那么后面的部分的索引将不能被使用,因为后面部分的索引数据是无序。比如,索引key(a,b)中的元组数据为(0,100)、(1,50)、(1,100) ,where查询条件为 a < 2 and b = 100。由于b上得索引数据并不是连续区间,因为在读取(1,50)之后不再会读取(1,100),mysql优化器在执行索引区间扫描之后也不再扫描组合索引其后面的部分。
表结构定义如下:
|
1
2
3
4
5
6
7
8
9
10
11
|
CREATE TABLE `person` (`person_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,`postadlcode` int(11) DEFAULT NULL,`age` tinyint(4) DEFAULT NULL,`first_name` varchar(45) NOT NULL,`last_name` varchar(45) NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`person_id`),KEY `idx_p_a` (`postadlcode`,`age`),KEY `idx_f_l` (`first_name`,`last_name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
关闭ICP优化,Extra信息为“Using Where”
|
1
2
3
4
5
6
7
|
mysql> set optimizer_switch = "index_condition_pushdown=off";mysql> explain select * from person where postadlcode between 300000 and 400000 and age > 40;+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+| 1 | SIMPLE | person | range | idx_p_a | idx_p_a | 7 | NULL | 21 | Using where |+----+-------------+--------+-------+---------------+---------+---------+------+------+-------------+ |
开启ICP之后,Extra信息为“Using Index Condition”
|
1
2
3
4
5
6
7
|
mysql> set optimizer_switch = "index_condition_pushdown=on";mysql> explain select * from person where postadlcode between 300000 and 400000 and age > 40;+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+| 1 | SIMPLE | person | range | idx_p_a | idx_p_a | 7 | NULL | 21 | Using index condition |+----+-------------+--------+-------+---------------+---------+---------+------+------+-----------------------+ |
SHOW PROFILING;
案例一:MySQL Sending data导致查询很慢的问题详细分析
1. 现象:
使用show full processlist;观察发现大量相同的sql处于 sending data状态。
使用show profile for query 1;查看sending data的时间长达15s,而其它都可忽略。
2. 分析:
第一想到的是否结果集太大,但是实质上查询结果集才一行数据。那是什么问题呢?
查询一下“Sending data”状态的含义,原来这个状态的名称很具有误导性,所谓的“Sending data”并不是单纯的发送数据,而是包括“收集 + 发送 数据”。
3. 处理:
看到这里,不是发送数据的问题,自然是收集数据有问题,业务SQL信息如下:
SELECT *
FROM (`wb_oauth_session`)
WHERE `client_id` = ''
AND `site_id` = '53ec30121162c047'
AND `owner_type` = 'member'
AND `owner_id` = '';
使用explain得到是使用了前两列作为索引,于是进行选择性测试。
SELECT count(*)
FROM (`wb_oauth_session`)
WHERE `client_id` = ''
AND `site_id` = '53ec30121162c047';
得到的结果集非常大,而mysql的data filter在mysql server层实现,那么存储引擎层必须把这么大的结果集发送到server层进行条件过滤,这个过程花费了时间,是问题所在。
经测试owner_id列的选择性最好,于是删除(client_id,site_id)的复合索引,添加owner_id列的索引,优化索引非常明显,从15s到0.01s。
mysql explain和profiling的更多相关文章
- explain和profiling分析查询SQL时间
mysql可以通过profiling命令查看到执行查询SQL消耗的时间. 默认情况下,mysql是关闭profiling的,命令: select @@profiling; +------------- ...
- 子查询优化--explain与profiling分析语句
今天想的利用explain与progiling分析下语句然后进行优化.本文重点是如何通过explain与profiling分析SQL执行过程与性能.进而明白索引的重要性. 表的关系如下所示: 原始的查 ...
- 【转载】 mysql explain用法
转载链接: mysql explain用法 官网说明: http://dev.mysql.com/doc/refman/5.7/en/explain-output.html 参数: htt ...
- Mysql Explain 详解(转)
原文:http://www.cnitblog.com/aliyiyi08/archive/2008/09/09/48878.html 一.语法 explain < table_name > ...
- mysql explain详解
对于经常使用mysql的兄弟们,对explain一定不会陌生.当你在一条SELECT语句前放上关键词EXPLAIN,MySQL解释它将如何处理SELECT,提供有关表如何联合和以什么次序的信息.借助于 ...
- mysql explain用法和结果的含义
重点是第二种用法,需要深入的了解. 先看一个例子: mysql> explain select * from t_order; +----+-------------+---------+--- ...
- MYSQL EXPLAIN 很慢的原因
今天同事在查看一个SQL的执行计划的时候,EXPLAIN语句跑了2分钟.SQL命令类似: SELECT * FROM (SELECT USERID,COUNT(*) FROM TBNAME GROUP ...
- [转]MySQL Explain详解
在日常工作中,我们会有时会开慢查询去记录一些执行时间比较久的SQL语句,找出这些SQL语句并不意味着完事了,些时我们常常用到explain这个命令来查看一个这些SQL语句的执行计划,查看该SQL语句有 ...
- mysql explain 命令讲解
explian命令可以显示select语句的执行计划 explain的结果中每行对应select语句中的一个表,输出结果中的顺序是按照语句处理表的顺序. mysql使用嵌套循环来处理所有的join连接 ...
随机推荐
- scrollMenu,一款可滚动的菜单插件 兼容pc和移动端
这个菜单 有两种样式 , 也可以通过animate.css加不同的动画效果!滚动的方式也有两种 一种为通用的overflow,另外一种是better-scroll的滚动效果 在线链接地址 ht ...
- hack在微信等webview中无法修改document.title的情况
var $body = $('body'); document.title = '确认车牌'; // hack在微信等webview中无法修改document.title的情况 var $iframe ...
- React周末特训班
Document #react819_content a { text-decoration: none; color: #ef7b2e; border-bottom: 1px solid #ef7b ...
- java for循环
publicclass Test2 { staticboolean foo(char c) { System.out.print(c); returntrue; ...
- 建造者模式(Java与Kotlin版)
前文推送 设计模式 简单工厂模式(Java与Kotlin版) 工厂方法模式(Java与Kotlin版) 抽象工厂模式(Java与Kotlin版) Kotlin基础知识 Kotlin入门第一课:从对比J ...
- shell脚本中字符串的常见操作及"command not found"报错处理(附源码)
简介 昨天在通过shell脚本实现一个功能的时候,由于对shell处理字符串的方法有些不熟悉导致花了不少时间也犯了很多错误,因此将昨日的一些错误记录下来,避免以后再犯. 字符串的定义与赋值 # 定义S ...
- pc端的企业网站(IT修真院test9)详解一个响应式完成的pc端项目
一:引入bootstrap框架 昨天一直被bootstrap栅格系统折磨. why? 我本来想一边码字,一边学习栅格布局的.but不成功.这时我头脑已经昏了. 下午,我查看了bootstrap的官网, ...
- Struts2简诉
Struts2框架是基于MVC模式的开源,MVC模式是一种开发方式,主要作用是对组件之间进行隔离,M代表业务逻辑层,V代表视图层,C代表控制层.有利于代码的后期维:Struts2框架的源码主要来于We ...
- Selenium对浏览器支持的版本
最新的selenium与几种常用浏览器的版本兼容情况: selenium 3.4.0 : Mozilla GeckoDriver 0.18 -- Firefox 53 - 56 Google Ch ...
- NLP —— 图模型(一)隐马尔可夫模型(Hidden Markov model,HMM)
本文简单整理了以下内容: (一)贝叶斯网(Bayesian networks,有向图模型)简单回顾 (二)隐马尔可夫模型(Hidden Markov model,HMM) 写着写着还是写成了很规整的样 ...