mysql in和大于性能_MySQL中大于小于,IN,OR,BETWEEN性能比较-Fun言
在MySQL中经常会有朋友问关于大于小于,IN,OR,BETWEEN,哪个性能更好?
我想有很多朋友会用它们但确实不知道大于小于,IN,OR,BETWEEN性能哪个更好吧,下面总结一下关于大于小于,IN,OR,BETWEEN性能。
这里的查询条件有四种:>=和<=;between;or;in
这里id列是索引列,如果不是的话,三个查询都是全表扫描,性能差距应该不大。
1 准备环境
mysql> show create table tinG
*************************** 1. row ***************************
Table: tin
Create Table: CREATE TABLE `tin` (
`c1` int(11) NOT NULL AUTO_INCREMENT,
`c2` varchar(256) DEFAULT NULL,
PRIMARY KEY (`c1`)
) ENGINE=InnoDB AUTO_INCREMENT=5002 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
mysql> show create procedure init_tinG
*************************** 1. row ***************************
Procedure: init_tin
sql_mode: NO_ENGINE_SUBSTITUTION
Create Procedure: CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `init_tin`(cnt int)
begin
declare i int default 0;
repeat
insert into tin(c2) values(repeat('a', 100));
set i:= i+1;
until i > cnt
end repeat;
end
character_set_client: utf8
collation_connection: utf8_general_ci
Database Collation: latin1_swedish_ci
1 row in set (0.00 sec)
mysql> call init_tin(5000)G
2 查看执行计划
为了简单起见,选择[100,104]这个区间。
查询语句为:
SELECT * FROM tin where c1 >= 100 and c1 <= 104;
SELECT * FROM tin wherec1bewteen 100 and 104;
SELECT * FROM tin where c1 in (100, 101, 102, 103, 104);
SELECT * FROM tin where c1 = 100 or c1 = 101 or c1 = 102 or c1 = 103 or c1 = 104;
其中,在MySQL中 c1 >= 100 and c1 <= 104和 c1bewteen 100 and 104是等价的,下面选用前者进行比较。
首先查看explain输出,会发现三个语句的explain输出是一样的:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: tin
type: range
possible_keys: PRIMARY
key: PRIMARY
key_len: 4
ref: NULL
rows: 5
filtered: 100.00
Extra: Using where
1 row in set, 1 warning (0.00 sec)
MySQL5.6在information_schema中增加了optimizer_trace表,用于跟踪语句生成的执行计划的具体步骤,包含各种关键的优化步骤。
分别看下三种不同语句的执行代价:
1. SELECT * FROM tin where c1 >= 100 and c1 <= 104;
SELECT * FROM tin where c1 >=100 and c1 <=104;
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 5,
"ranges": [
"100 <= c1 <= 104"
]
},
"rows_for_plan": 5,
"cost_for_plan": 2.0188,
"chosen": true
}
2. SELECT * FROM tin where c1 in (100, 101, 102, 103, 104);
SELECT * FROM tin where c1 in (100, 101, 102, 103, 104);
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 5,
"ranges": [
"100 <= c1 <= 100",
"101 <= c1 <= 101",
"102 <= c1 <= 102",
"103 <= c1 <= 103",
"104 <= c1 <= 104"
]
},
"rows_for_plan": 5,
"cost_for_plan": 6.0188,
"chosen": true
}
3. SELECT * FROM tin where c1 = 100 or c1 = 101 or c1 = 102 or c1 = 103 or c1 = 104;
SELECT * FROM tin where c1 = 100 or c1 = 101 or c1 = 102 or c1 = 103 or c1 =104;
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "PRIMARY",
"rows": 5,
"ranges": [
"100 <= c1 <= 100",
"101 <= c1 <= 101",
"102 <= c1 <= 102",
"103 <= c1 <= 103",
"104 <= c1 <= 104"
]
},
"rows_for_plan": 5,
"cost_for_plan": 6.0188,
"chosen": true
}
从上面可以看出执行代价最小的语句为SELECT * FROM tin WHERE c1 >= 100 and c1 <=104,代价为2.0118,其他两个计划的代价 为6.0118。
3 计划分析
看了上面的代价结果,是不是就理所当然的任务第一个语句的代价真的是最小呢?
这就需要知道MySQL代价计算的方法, 一个计划的代价体现在硬件上就是I/O + CPU,I/O就是将所需的物理页载入内存的时间,CPU则是数据计算所消耗的时间, 有些语句是I/O密集的,有些语句是CPU运算密集的。
为什么MySQL计算出来的代价会差别这么大呢?
MySQL在计算上面三个语句的代价时,I/O代价的计算是由range的个数n_ranges和最终的结果集的行数total_rows得出来的,
语句1的n_ranges=1
语句2和语句3的n_ranges=5
totol_rows都为5
故语句1的在I/O上的代价明显小于语句2和语句3(具体的函数参见ha_innobase::read_time)。
至于CPU的代价,由于返回的行数一致,故CPU的代价一致,CPU的代价主要体现在获取数据后,进行WHERE 条件的匹配操作。
这只是MySQL的对于上面三个语句的代价模型,而实际上,上面三个语句所进行的I/O操作其实是一致的,因为数据范围是一样的。所以,仅凭 MySQL给出的代价结果还是不能立刻判断出语句1就肯定好。
既然I/O操作的代价可以考虑是一致的,那么只能来看三条语句执行时的区别了。
语句2和语句3的range个数都为5个,而且range的范围都是一致的, 这其实是MySQL的优化结果,IN和OR都被优化成了相同的结果。只有语句1只有1个range。MySQL执行时是遍历每个range,而每个range遍历时其实是两种操作,read_first和read_next,read_first是根据每个range的start key定位到相应的位置,read_next则是根据上次BTREE读到的位置, 继续往后读,read_next是以end key为结束。
对于语句1,只有一个range,故需要1次read_first和5次read_next(最后一次read_next不符合end_key,返回结束)
对于语句2和语句3, 有5个range,每个range需要1此read_first和一次read_next,总共需要5此read_first和5次read_next。
从数据获取的次数来看,语句2和语句3基本是语句1的调用次数的两倍。
合法性的验证
除了获取数据调用次数的区别外,在获取数据之后,还需要进行数据合法性的验证,即匹配WHERE条件。
对于语句1的WHERE条件十分简单,匹配上下界限即可,即对于每返回的一行数据需要两次验证,时间复杂度为常量O(2)。
对于语句2和语句3,则需要对IN或OR中的每个条件进行验证,知道找到某一匹配项为止,时间复杂度为O(n)。 但是MySQL对于IN做了相应的优化,即将IN中的常量全部存储在一个数组里面,而且这个数组是排好序的,故匹配的时候是二分查找,时间复杂度为O(lgn)。
在忽略I/O的情况下,仅仅从CPU的耗时来看,语句1应该是最少的,其次是IN,最差的就是OR
先就分析到这吧,具体的执行时间的数据这里没测试,感兴趣的可以进一步测试下!
上面是想通过测试了解MySQL内部的优化流程,可能单独测试的时候语句执行效率差别不是很大。
mysql in和大于性能_MySQL中大于小于,IN,OR,BETWEEN性能比较-Fun言相关推荐
- mysql去重复查询 性能_MySQL中distinct语句去查询重复记录及相关的性能讨论_MySQL...
在 MySQL 查询中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值,就是去重啦.用法也很简单: SELE ...
- mysql去重复查询 性能_MySQL中distinct语句去查询重复记录及相关的性能讨论
在 MySQL 查询中,可能会包含重复值.这并不成问题,不过,有时您也许希望仅仅列出不同(distinct)的值. 关键词 DISTINCT 用于返回唯一不同的值,就是去重啦.用法也很简单: SELE ...
- mysql 隐式主键_MySQL中复合主键性能的缺点
我们有一个表,该表具有由三个字段组成的复合主键(在MySQL 5.1中是这样). 该表上每秒有近200个插入和200个选择,并且表的大小约为100万行,并且还在不断增加. 我的问题是:"复合 ...
- mysql查询id为偶数_MySQL中查询中位数?
导读:计算中位数可能是小学的内容,然而在数据库查询中实现却并不是一件容易的事.我们今天就来看看都有哪些方法可以实现. 注:本文所用MySQL版本无限制,所列题目均来源于LeetCode. LeetCo ...
- mysql 子查询怎么写_MySQL中两种子查询的写法
MySQL的测试环境 测试表如下 create table test_table2 ( id int auto_increment primary key, pay_id int, pay_time ...
- mysql的collate什么意思_MYSQL中的COLLATE是什么?
在mysql中执行show create table 指令,可以看到一张表的建表语句,example如下: CREATE TABLE `table1` ( `id` bigint(20) unsign ...
- mysql获取当前的月_MYSQL中获取当前的年和月
展开全部 select year(curdate()),month(curdate()),day(curdate()); select weekofyear(curdate()); 有点细微的差别,w ...
- mysql的explain怎么看_mysql中explain用法详解
如果在select语句前放上关键词explain,mysql将解释它如何处理select,提供有关表如何联接和联接的次序. explain的每个输出行提供一个表的相关信息,并且每个行包括下面的列: 1 ...
- mysql创建临时表 主键_MySQL中临时表的基本创建与使用教程
当工作在非常大的表上时,你可能偶尔需要运行很多查询获得一个大量数据的小的子集,不是对整个表运行这些查询,而是让MySQL每次找出所需的少数记录,将记录选择到一个临时表可能更快些,然后在这些表运行查询. ...
最新文章
- SpringSession(redis)
- php自动post系统,php自动过滤POST,GET传参
- golang连接mysql报错:this authentication plugin is not supported 解决方案
- U盘中的autorun.inf
- Spring和Mybatis集成,如何批量insert update?以及一些通用Dao的设想
- 一个小程序的首页对接后端实现用户注册
- PAT甲级1030 Travel Plan (30分):[C++题解]dijkstra求单源最短路、保存路径
- ecm工作原理 usb_“好玩具”来了!往你的USB端口里藏入一个小开发板...
- Linux open函数使用方法记录
- string转map集合_集合(下)
- 面试官系统精讲Java源码及大厂真题 - 29 押宝线程源码面试题
- 设计一个高质量的 API 接口
- 从Q-learning到PPO大全 深度强化学习总结和理解
- 处理 TXT 文本技巧
- UVM-factory机制
- 抖音返利分销模式及代理系统开发
- 又一个奇葩要求,Python是如何将“中文”转“拼音”的?
- 81 文件操作——关闭文件
- leetcode解题思路分析(一百三十二)1111 - 1117 题
- expected 3 got 2 错误提示