索引使用,分析初探。(explain分析执行计划,以及强制使用force index)
促使这次探索的初衷还是因为要对一个定时脚本性能进行优化。
脚本有两个指定状态分别是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)的更多相关文章
- SQL优化 MySQL版 -分析explain SQL执行计划与笛卡尔积
SQL优化 MySQL版 -分析explain SQL执行计划 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 首先我们先创建一个数据库,数据库中分别写三张表来存储数据; course: ...
- SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)
本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...
- MySQL 使用explain查看执行计划
使用explain查看执行计划, 下面是针对这两条语句进行分析,其查询结果是一样的. EXPLAIN select n.id,n.title from info n inner join info_t ...
- 引用:初探Sql Server 执行计划及Sql查询优化
原文:引用:初探Sql Server 执行计划及Sql查询优化 初探Sql Server 执行计划及Sql查询优化 收藏 MSSQL优化之————探索MSSQL执行计划 作者:no_mIss 最近总想 ...
- hive高阶1--sql和hive语句执行顺序、explain查看执行计划、group by生成MR
hive语句执行顺序 msyql语句执行顺序 代码写的顺序: select ... from... where.... group by... having... order by.. 或者 from ...
- PostgreSQL执行计划:Bitmap scan VS index only scan
之前了解过postgresql的Bitmap scan,只是粗略地了解到是通过标记数据页面来实现数据检索的,执行计划中的的Bitmap scan一些细节并不十分清楚.这里借助一个执行计划来分析bitm ...
- SQL优化 MySQL版 -分析explain SQL执行计划与Extra
Extra 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 注:此文章必须有一定的Mysql基础,或观看执行计划入门篇传送门: https:.html 终于总结到哦SQK执行计划的最 ...
- 详解GaussDB(DWS) explain分布式执行计划
摘要:本文主要介绍如何详细解读GaussDB(DWS)产生的分布式执行计划,从计划中发现性能调优点. 前言 执行计划(又称解释计划)是数据库执行SQL语句的具体步骤,例如通过索引还是全表扫描访问表中的 ...
- MySQL执行计划extra中的using index 和 using where using index 的区别
本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
随机推荐
- UVA1434-The Rotation Game(迭代加深搜索)
Problem UVA1434-The Rotation Game Accept:2209 Submit:203 Time Limit: 3000 mSec Problem Description ...
- Tmux的快捷键
Ctrl+b 激活控制台:此时以下按键生效 系统操作 ? 列出所有快捷键:按q返回 d 脱离当前会话:这样可以暂时返回Shell界面,输入tmux attach能够重新进入之前的会话 D 选择要脱离的 ...
- 转://使用insert插入大量数据的总结
使用insert插入大量数据的个人经验总结在很多时候,我们会需要对一个表进行插入大量的数据,并且希望在尽可能短的时间内完成该工作,这里,和大家分享下我平时在做大量数据insert的一些经验. 前提:在 ...
- multi函数
def multi(*a): sum = 1 for i in a: sum = sum *i return sum 若干个参数 百度了一下
- apt-get update 更新 ubuntu时出现Hash sum mismatch的原因及解决方法
$ sudo apt-get update ...... Hit http://mirrors.163.com trusty/main Sources ...
- 初学Python——软件目录结构规范
为什么要设计好目录结构? 可读性高: 不熟悉这个项目的代码的人,一眼就能看懂目录结构,知道程序启动脚本是哪个,测试目录在哪儿,配置文件在哪儿等等.从而非常快速的了解这个项目. 可维护性高: 定义好组织 ...
- Android测试(一):在Android中测试App
原文:https://developer.android.com/training/testing/index.html 测试你的App是开发过程中的重要组成部分.通过对应用程序持续的运行测试,你可以 ...
- machine learning[GMM-EM]
介绍下EM算法和GMM模型,先简单介绍GMM的物理意义,然后给出最直接的迭代过程:然后再介绍EM. 1 高斯混合模型 高斯分布,是统计学中的模型,其输出值表示当前输入数据样本(一维标量,多维向量)的概 ...
- go项目
1.循环使用缓存 每条日志需要开辟缓存块来存储内容,以减少频繁的内存分配与回收.日志结构体定义如下: type MLogger struct { // freeList is a list of by ...
- python数据类型--set(集合)
博客地址:http://www.cnblogs.com/yudanqu/ 首先,简单介绍一下set,set就是我们中学时所学的集合,当时集合的性质就包括一点,集合里不能有重复的数字.我们现在所用到的集 ...