MySQL中in(常量列表)的执行计划
我们在写sql的时候,经常用到in,in后面跟一堆常量列表,如id。有人说in的效率很高,而有人说很低;有人说in能使用索引,还有人说in不能使用索引。。。
到底是一个怎样的情况呢?我们分析以下几种情况
在这之前,我们先了解一下explain的几种type类型(本次分析即参照type类型),按照性能从高到低:
const:表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待
eq_ref:在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用
ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好
range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况
index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)
ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免
一,in后面只有1个值
1.1 对于主键或者唯一索引,那么type=const,这种性能最高,表示表中只有1个记录能满足查询
1.2 对于普通索引、或者联合主键,type=ref
1.3 对于普通字段,type=all,这种性能最差
二,in后面多余1个值,但少于某一个值,这个值具体是多少,之后会揭晓。
这时,不管是主键,还是唯一索引,还是普通索引,type=range
但是在这里需要注意的一个特例是:当你的索引的Cardinality属性比较低时,type=all,意思就是这个索引的区分度很低,建立的意义不大,
这时他的执行计划type=all,mysql认为走这个索引还不如全表扫描:
到底Cardinality处于什么水平时,性能最好?一般认为这个值越接近count(*),性能最好。而对于像性别这种字段,就没必要加索引了。
三,相对于第二种情况,当in后面的值多于某一个值,会导致扫描全表。这个经验值我目前不能确定,咨询过相关DBA,他们也不能给出其经验值
3.1 test1表总共27条数据,当in后面的值少于8个时,type=range,而当超过8个时,type=all,如下:
3.2 这个t_word_cost表,总共有38244条数据,word_id上有索引,我测试了一把,当in后面不超过5千多或者6千多时,type=range,这是什么意思?
因为令我不解的是,这个值还不确定,它是波动的,我执行了好多次,有时候是5千多,有时候是6千多,或者其他值
通过对test1、t_word_cost表进行测试,我确实没有找出规律来,我原来妄想,通过大量实践得出一个经验值,然后通过经验值来判断到底in后面的个数占count(*)百分比多少的时候,能走索引,看来我徒劳了。
既然不能得出经验值,那我们只有在实际应用环境下具体选择解决方案了。
譬如我这次操作t_word_cost表,in后面值的个数都超过count(*)了,如果一次性全部写进in后面,一次查询所耗时间是30-40s左右!
根据上面我分析的结果,貌似我应该选择5000作为临界值,然后分批、多次查询,这样性能应该最高。但实际情况是这样吗?
通过我在程序中不断地人肉测试发现,并不是5000耗时最少,选择2000或者2500时,总体耗时最少,至于为什么,可能与内存、频繁的数据库连接有关吧,
因为我们知道,内存、IO都会影响整体性能,所以怎样平衡这个度需要自己把握。
MySQL中in(常量列表)的执行计划的更多相关文章
- [转]Mysql中的SQL优化与执行计划
From : http://religiose.iteye.com/blog/1685537 一,如何判断SQL的执行效率? 通过explain 关键字分析效率低的SQL执行计划. 比如: expla ...
- Mysql中的sql是如何执行的 --- 极客时间学习笔记
MySQL中的SQL是如何执行的 MySQL是典型的C/S架构,也就是Client/Server架构,服务器端程序使用的mysqld.整体的MySQL流程如下图所示: MySQL是有三层组成: 连接层 ...
- MySQL——通过EXPLAIN分析SQL的执行计划
在MySQL中,我们可以通过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序. 下面分别对EXPLAIN命令结果的每一列进行说明: ...
- 高性能可扩展mysql 笔记(六) SQL执行计划及分页查询优化、分区键统计
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 常见业务处理 一.使用数据库处理常见业务: 案例: 如何对评论进行分页展示 使用 EXPLAIN 获得s ...
- Mysql中explain命令查看语句执行概况
Mysql中可以使用explain命令查看查询语句的执行方式,使用方法举例:explain + 查询语句 例如:explain select * from user_info 几个重要的字段说明: t ...
- Mysql学习---视图/触发器/存储过程/函数/执行计划/sql优化 180101
视图 视图: 视图是一个虚拟表(非真实存在),动态获取数据,仅仅能做查询操作 本质:[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当作表来使用.由 ...
- oracle中查看sql语句的执行计划
1.在pl/sql中打开cmd命令容器 2.在cmd命令窗口中输入:explain plan for select * from t; 3.查看sql语句的执行计划:select * from tab ...
- [转]使用mysql profiles 来查看sql 语句执行计划
From : http://blog.csdn.net/radkitty/article/details/4632289 要使用该功能,mysql的版本必须在5.0.37版本以上.否则只能使用expl ...
- mysql中插入序列表
利用序列表来实现列转行:CREATE TABLE sequence(id INT UNSIGNED NOT NULL auto_increment PRIMARY KEY)往里面插入数据 INSERT ...
- MySQL 查看执行计划
MySQL 使用 explain + sql 语句查看 执行计划,该执行计划不一定完全正确但是可以参考. EXPLAIN SELECT * FROM user WHERE nid = 3; selec ...
随机推荐
- #422 Div2 D
#422 Div2 D 题意 假设有 n 个人比赛,每次比赛进行分组,每组人数必须相同,如果一组有 x 人,则那一组要比赛 $ \frac{x * (x - 1)}{2}$次,最终一人获胜,其它人淘汰 ...
- SQL PARTITION BY:列值改变时重置计数
现有数据如下: 需求:以科目为单位 对分数进行排序 SELECT *, ROW_NUMBER() OVER (PARTITION BY 科目 ORDER BY 分数 DESC) AS NUM FROM ...
- HDU 2586 How far away? LCA 转化成RMQ
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 [题意] 给出一个N 个和N-1条边的连通图,询问任意两点间的距离.N<=40000 . [分 ...
- 【译】PHP之道(PHP the right way)
刚入门的同学觉得自己能用PHP写出各种程序就很NB了,但其实作为一个专业程序员,你得有个全面点的知识结构.单元测试总得听过,文档工具总得用用,Xss总得会防.推荐大家把<PHP the righ ...
- 【视频】 Linux高级程序设计01.2开发平台及Linux环境限制
[课程笔记] Linux环境限制 遵循规范,使用现有资源,明确系统限制,增量开发. (1)规范问题 编码的规范,让程序更易读.Linux编码规范. “见着如意”:变量,函数命名等能够让人看到名称就知道 ...
- 编译qt提示找不到gmake
转:http://wuyuans.com/2012/11/gmake-not-found/ 在用debian编译qt4.5的时候提示gmake: not found,gmake是什么东西,用aptit ...
- c# Http Post访问接口方式
一.json格式数据提交返回 提交和返回数据都为json格式 参数提交方式:application/json;charset=UTF-8 统一采用UTF-8字符编码 public string Pos ...
- nginx静态文件访问404
在http模块下加入下面的代码 server { listen 80; server_name 192.168.1.249; #本机ip #access_log logs/host.access.lo ...
- APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate notice, with the fields e ...
- linux selenium运行chrome
chrome版本要和chromedriver版本匹配才能正常运行.