促使这次探索的初衷还是因为要对一个定时脚本性能进行优化。

脚本有两个指定状态分别是status, latest_process_status,和一个超期时间expire_time进行限制。

按照我以前的习惯,直接给这一组字段建了一个联合索引。写成了 expire_time_status_latest_process_status (expire_time, status, latest_process_status)

以前只知道,联合索引的第一个值会做单独的索引,但是不知道先后顺序不同也会导致索引检查的顺序不同。

建完之后想来查看一下语句究竟会按照何种套路执行,去搜了一下如何分析,看到了执行计划。使用了之后发现大概能知道有没有用索引,有哪些备选索引,需要怎么扫描之类。 先来看个例子。

*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: ec_customer_service
partitions: NULL
type: range
possible_keys: expire_time_latest_process_status_status
key: expire_time_latest_process_status_status
key_len: 6
ref: NULL
rows: 95172
filtered: 25.00
Extra: Using index condition

select_type: 查询的类型,这歌例子里面是一个简单查询的列子,对应的还有复杂查询,拥有自查询的复杂查询会显示不止一列。

table: 预计会操作的表

type: 表示mysql 执行计划预测会如何去访问表中的数据,这列有all, index, ref, const range, eq_ref, null 这7种。在这里显示的ref代表的是索引扫描,而且会与某些值进行参照。经常见到的type还有 all 和 range,一个代表全表扫描,一个代表范围查找,范围查找一边会用到><=类似这种范围型的条件。

possible_keys: 可能会选择的索引,如果有多个索引可用,这里会全部列出来。

key: 执行计划会使用的索引。

key_len: 索引长度。

ref: 这个我没太明白。。应该是参照key有个什么关系。

rows: 预计会扫描多少行。

Extra: 特别需要提到的信息:

这一列包含的是不适合在其他列显示的额外信息。mysql用户手册里记录了大多数可以在这里出现的值。
常见的最重要的值如下。
“Using index”
    此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
“Using where”
    这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
“Using temporary”
    这意味着mysql在对查询结果排序时会使用一个临时表。
“Using filesort”
    这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
“Range checked for each record(index map: N)”
    这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。

上面提到了一个索引覆盖,这里说下,索引覆盖无需访问数据文件,直接读取索引文件进行返回。速度快的飞起,这一点可以从查找行数rows字段看出来。

通过上面的例子我们可以看出来,这里我需要用到的信息是行数rows和key 看一下是用到了哪个索引,并且同时看下执行需要扫描多少行才可以。说一下,这里数据一共是20w行,可以看到在使用这个索引的情况下竟然执行计划要扫描近10w行数据,可见效率是不高的。

为什么我在建立了看似不错的联合索引,效率才这么低。分析上面的sql语句不难发现,其实索引起最大作用的不应该是expire_time这个只规划了一个范围的字段,而是在status和latest_process_status上面,特别是status状态,在判断了多个状态的情况,是非常消耗查询时间的。我们不妨使用status做一个单索引来看一下开销

mysql> explain select * from ec_customer_service where expire_time<'2017-01-11' and status=1 and latest_process_status in (1000, 1001, 1002, 1003, 1004,1005);
+----+-------------+---------------------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------------+------+---------------+--------+---------+-------+------+-------------+
| 1 | SIMPLE | ec_customer_service | ref | status | status | 4 | const | 1003 | Using where |
+----+-------------+---------------------+------+---------------+--------+---------+-------+------+-------------+

不难发现,居然只需要 扫描1003行就可以解决问题?快了近90倍。。 可见索引并不是把要查询的字段都包含进去就可以了这么简单,而是要更详细的分析自己使用的语句到底哪个字段或者哪几个字段做成目录可以提升查询效率。

如果我们同时建立好几个相关字段索引,在查看执行计划的时候,在possible_keys字段可以看到这些相关索引被罗列出来。 我们还可以通过在where前使用 「force index (索引字段)」 来强制语句使用该索引,因为mysql语句在执行的时候,引擎并不总是会做出最优判断,你可以自己通过调整和查看执行计划,或者别的参数设置再结合自己的经验强制使用某个字段做搜索索引,从而提升搜索速度。

在这个例子中,我也尝试建立了类似 status_latest_process_status_expire_time这种联合索引,效果其实和status差不多,同样需要扫描近1000个字段,提升不大。而且filtered字段的值还会提升到达接近50%,key_lenth字段也变得很长,因为数据量并非 特别大,我还没有测试出filtered字段增大对性能带来的影响,但是如果能使用一个或两个索引字段就能搞定的事情,为什么要使用多个呢?

Reference:

http://blog.itpub.net/29773961/viewspace-1767044/   MySQL 执行计划explain详解

索引使用,分析初探。(explain分析执行计划,以及强制使用force index)的更多相关文章

  1. SQL优化 MySQL版 -分析explain SQL执行计划与笛卡尔积

    SQL优化 MySQL版 -分析explain SQL执行计划 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 首先我们先创建一个数据库,数据库中分别写三张表来存储数据; course: ...

  2. SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)

    本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...

  3. MySQL 使用explain查看执行计划

    使用explain查看执行计划, 下面是针对这两条语句进行分析,其查询结果是一样的. EXPLAIN select n.id,n.title from info n inner join info_t ...

  4. 引用:初探Sql Server 执行计划及Sql查询优化

    原文:引用:初探Sql Server 执行计划及Sql查询优化 初探Sql Server 执行计划及Sql查询优化 收藏 MSSQL优化之————探索MSSQL执行计划 作者:no_mIss 最近总想 ...

  5. hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR

    hive语句执行顺序 msyql语句执行顺序 代码写的顺序: select ... from... where.... group by... having... order by.. 或者 from ...

  6. PostgreSQL执行计划:Bitmap scan VS index only scan

    之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...

  7. SQL优化 MySQL版 -分析explain SQL执行计划与Extra

    Extra 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:此文章必须有一定的Mysql基础,或观看执行计划入门篇传送门: https:.html 终于总结到哦SQK执行计划的最 ...

  8. 详解GaussDB(DWS) explain分布式执行计划

    摘要:本文主要介绍如何详细解读GaussDB(DWS)产生的分布式执行计划,从计划中发现性能调优点. 前言 执行计划(又称解释计划)是数据库执行SQL语句的具体步骤,例如通过索引还是全表扫描访问表中的 ...

  9. MySQL执行计划extra中的using index 和 using where using index 的区别

    本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

随机推荐

  1. 图上最短路(Dijkstra, spfa)

    单源最短路径 题目描述 如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度. 输入输出格式 输入格式: 第一行包含三个整数N.M.S,分别表示点的个数.有向边的个数.出发点的编号. 接下来 ...

  2. ansible-playbook 进行批量安装tomcat8

    ansible-playbook 进行安装tomcat操作 说明: get_url  中下载的内容直接到目的主机 安装的时候需要指定copy: no,说明需直接从目标主机进行安装包 [root@ans ...

  3. ubantu下Navicat乱码的问题

    在官网下载的最新版的Navivat12出现的乱码情况 解决方法:Navicat的文件夹中找到start_navicat用vim编辑,在export LANG=“en_US.UTF-8”这句话改为exp ...

  4. ActiveMQ的作用总结(应用场景及优势)

    业务场景说明: 消息队列在大型电子商务类网站,如京东.淘宝.去哪儿等网站有着深入的应用, 队列的主要作用是消除高并发访问高峰,加快网站的响应速度. 在不使用消息队列的情况下,用户的请求数据直接写入数据 ...

  5. 快看Sample代码,速学Swift语言(3)-运算符

    运算符是用来检查,更改或组合值的特殊符号或短语.Swift提供的很多常规的运算符,如+.-.*./.%.=.==等,以及逻辑运算的&&.||等等,基本上不需要重复介绍,我们在这里只需要 ...

  6. 深入理解JAVA虚拟机(内存模型+GC算法+JVM调优)

    目录 1.Java虚拟机内存模型 1.1 程序计数器 1.2 Java虚拟机栈 局部变量 1.3 本地方法栈 1.4 Java堆 1.5 方法区(永久区.元空间) 附图 2.JVM内存分配参数 2.1 ...

  7. 多模块后带来的问题解决方法 - OSGI原形(.NET)

    目前只做了基础的功能,比如: 各个模块单独的AppDomain容器 Activator激活 导出的服务检查 不过,虽说这样,但目前的这个版本已经能实现模块分离.互相依赖调用等功能了,对模块划分已经有很 ...

  8. redis-trib.rb命令详解

    redis-trib.rb是官方提供的Redis Cluster的管理工具,无需额外下载,默认位于源码包的src目录下,但因该工具是用ruby开发的,所以需要准备相关的依赖环境. 准备redis-tr ...

  9. python读取/创建XML文件

    Python中定义了很多处理XML的函数,如xml.dom,它会在处理文件之前,将根据xml文件构建的树状数据存在内存.还有xml.sax,它实现了SAX API,这个模块牺牲了便捷性,换取了速度和减 ...

  10. hdu 5584 LCM Walk

    没用运用好式子...想想其实很简单,首先应该分析,由于每次加一个LCM是大于等于其中任何一个数的,那么我LCM加在哪个数上面,那个数就是会变成大的,这样想,我们就知道,每个(x,y)对应就一种情况. ...