0

0

MySQL InternalsIN,OR,BETWEEN哪个更快?_MySQL

php中文网

php中文网

发布时间:2016-06-01 13:36:15

|

1167人浏览过

|

来源于php中文网

原创

bitsCN.com


MySQL Internals——IN,OR,BETWEEN哪个更快?

Louis Hust

 

0  前言

微博上看到@金山 提到了一个mysql中的一个性能问题,

 

select id from table where id > 100 and id  

哪个更快?

 

这里的查询条件有三种:between,or 和 in。这里id列是索引列,如果不是的话,三个查询都是全表扫描,性能差距应该不大。

 

1  准备环境

mysql> show create table tin/G*************************** 1. row ***************************       Table: tinCreate 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=latin11 row in set (0.00 sec)mysql> show create procedure init_tin/G*************************** 1. row ***************************           Procedure: init_tin            sql_mode: NO_ENGINE_SUBSTITUTION    Create Procedure: CREATE DEFINER=`root`@`127.0.0.1` PROCEDURE `init_tin`(cnt int)begindeclare i int default 0;repeatinsert into tin(c2) values(repeat('a', 100));set i:= i+1;until i > cntend repeat;endcharacter_set_client: utf8collation_connection: utf8_general_ci  Database Collation: latin1_swedish_ci1 row in set (0.00 sec)mysql> call init_tin(5000)/G
 

2  查看执行计划

为了简单起见,这里并没有选择[100,200]这个区间进行查询,而是只选择了[100,104]这个区间。 查询语句为:

 

SELECT * FROM tin where c1 >= 100 and c1 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;

 

首先查看explain输出,会发现三个语句的explain输出是一样的:

*************************** 1. row ***************************           id: 1  select_type: SIMPLE        table: tin         type: rangepossible_keys: PRIMARY          key: PRIMARY      key_len: 4          ref: NULL         rows: 5     filtered: 100.00        Extra: Using where1 row in set, 1 warning (0.00 sec)
 

MySQL5.6在information_schema中增加了optimizer_trace表,用于跟踪语句生成的执行计划的具体步骤,包含各种关键的优化步骤。 分别看下三种不同语句的执行代价:

1. 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);"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;"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  

3  计划分析

看了上面的代价结果,是不是就理所当然的任务第一个语句的代价真的是最小呢?这就需要知道MySQL代价计算的方法, 一个计划的代价体现在硬件上就是I/O+CPU,I/O就是将所需的物理页载入内存的时间,CPU则是数据计算所消耗的时间, 有些语句是I/O密集的,有些语句是CPU运算密集的。

Subtxt
Subtxt

生成有意义的文本并编写完整的故事。

下载
 

为什么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内部的优化流程。可能单独测试的时候语句执行效率 差别不是很大。好了,收拾行李,明天回家,年前最后一篇。


File translated fromTEXby TTH,version 4.03.
On 7 Feb 2013, 22:39.

bitsCN.com

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Word 字间距调整方法汇总
Word 字间距调整方法汇总

本专题整合了Word字间距调整方法,阅读下面的文章了解更详细操作。

2

2025.12.24

任务管理器教程
任务管理器教程

本专题整合了任务管理器相关教程,阅读下面的文章了解更多详细操作。

2

2025.12.24

AppleID格式
AppleID格式

本专题整合了AppleID相关内容,阅读专题下面的文章了解更多详细教程。

0

2025.12.24

csgo视频观看入口合集
csgo视频观看入口合集

本专题整合了csgo观看入口合集,阅读下面的文章了知道更多入口地址。

29

2025.12.24

yandex外贸入口合集
yandex外贸入口合集

本专题汇总了yandex外贸入口地址,阅读下面的文章了解更多内容。

58

2025.12.24

添加脚注通用方法
添加脚注通用方法

本专题整合了添加脚注方法合集,阅读专题下面的文章了解更多内容。

1

2025.12.24

重启电脑教程汇总
重启电脑教程汇总

本专题整合了重启电脑操作教程,阅读下面的文章了解更多详细教程。

3

2025.12.24

纸张尺寸汇总
纸张尺寸汇总

本专题整合了纸张尺寸相关内容,阅读专题下面的文章了解更多内容。

5

2025.12.24

Java Spring Boot 微服务实战
Java Spring Boot 微服务实战

本专题深入讲解 Java Spring Boot 在微服务架构中的应用,内容涵盖服务注册与发现、REST API开发、配置中心、负载均衡、熔断与限流、日志与监控。通过实际项目案例(如电商订单系统),帮助开发者掌握 从单体应用迁移到高可用微服务系统的完整流程与实战能力。

1

2025.12.24

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号