OR、in和union all 查询效率到底哪个快。

网上很多的声音都是说union all 快于 or、in,因为or、in会导致全表扫描,他们给出了很多的实例。

但真的union all真的快于or、in?本文就是采用实际的实例来探讨到底是它们之间的效率。

1:创建表,插入数据、数据量为1千万【要不效果不明显】。

  1. drop table if EXISTS BT;
  2. create table BT(
  3. ID int(10) NOT NUll,
  4. VName varchar(20) DEFAULT '' NOT NULL,
  5. PRIMARY key( ID )
  6. )ENGINE=INNODB;

该表只有两个字段 ID为主键【索引页类似】,一个是普通的字段。(偷懒就用简单的表结构呢)

向BT表中插入1千万条数据

这里我写了一个简单的存储过程【所以你的mysql版本至少大于5.0,俺的版本为5.1】,代码如下。

注意:最好

INSERT INTO BT ( ID,VNAME )  VALUES( i, CONCAT( 'M', i ) );---1

修改为

INSERT INTO BT ( ID,VNAME )  VALUES( i, CONCAT( 'M', i, 'TT' ) );---2

修改原因在

   非索引列及VNAME使用了联合进行完全扫描请使用1 

非索引列及VNAME使用了全表扫描请使用2 

  1. DROP PROCEDURE IF EXISTS test_proc;
  2. CREATE PROCEDURE test_proc()
  3. BEGIN
  4. declare i int default 0;
  5. set autocommit = 0;
  6. while i<10000000 do
  7. INSERT INTO BT ( ID,VNAME )  VALUES( i, CONCAT( 'M', i ) );
  8. set i = i+1;
  9. if i%2000 = 0 then
  10. commit;
  11. end if;
  12. end while;
  13. END;

就不写注释呢,挺简单的。

存储过程是最好设置下innob的相关参数【主要和日志、写缓存相关这样能加快插入】,俺没有设置插入1千万条数据插了6分钟。

部分数据如下:1千万数据类似

2:实战

2.1 :分别在索引列上使用 or、in、union all

我们创建的表只有主键索引,所以只能用ID做查询呢。我们查 ID 为 98,85220,9888589的三个数据各个耗时如下:

时间都为0.00,怎么会这样呢,呵呵所有查询都是在毫秒级别。

我使用其他的工具--EMS SQL Manager  for mysql

查询显示时间为

93 ms, 94ms,93 ms,时间相差了多少几乎可以忽略。

然后我们在看看各自的执行计划

这里要注意的字段type 与ref字段

我们发现union all 的所用的 type【type为显示连接使用了何种类型】 为ref 而or和in为range【ref连接类型优于range,相差不了多少】,而查询行数都一样【看rows字段都是为3】。

从整个的过程来看,在索引列使用常数or及in和union all查询相差不了多少。

但为什么在有的复杂查询中,再索引列使用or及in 比union all 速度很多呢,这可能是你的查询写的不够合理,让mysql放弃索引而进行全表扫描。

2.2:在非索引列中使用 or、in及union all

我们查 VNAME 为 M98,M85220,M9888589的三个数据各个耗时如下:

我们发现为啥union all查询时间几乎为 or 和in的三倍。

这是为什么呢,我们先不说,先看看三个的查询计划。

这里我们发现计划几乎一样。

但我们要注意扫描的此时对于 or及in 来说 只对表扫描一次即rows是列为9664782。

而对于union all 来说对表扫描了三次即rows的和为9664782*3。

这也是为什么我们看到union all 为几乎为三倍的原因。

备注: 如果使用存储过程使用第二sql该执行计划所有的type列 为 all,其实这个是我最想演示的,但现在已经快写完毕了才发现问题将错就错呢。

3:总结

 3.1:不要迷信union all 就比 or及in 快,要结合实际情况分析到底使用哪种情况。

     3.2:对于索引列来最好使用union all,因复杂的查询【包含运算等】将使or、in放弃索引而全表扫描,除非你能确定or、in会使用索引。

    3.3:对于只有非索引字段来说你就老老实实的用or 或者in,因为 非索引字段本来要全表扫描而union all 只成倍增加表扫描的次数。

    3.4:对于及有索引字段【索引字段有效】又包含非索引字段来时,按理你也使用or 、in或者union all 都可以,

       但是我推荐使用or、in。

如以下查询:

  1. select * from bt where bt.VName = 'M98' or bt.id ='9888589'
  2. select * from bt where bt.VName = 'M98'
  3. UNION ALL
  4. select * from bt where  bt.id = '9888589'

该两个查询速度相差多少 主要取决于 索引列查询时长,如索引列查询时间太长的话,那你也用or或者in代替吧。

3.5: 以上主要针对的是单表,而多表联合查询来说,考虑的地方就比较多了,比如连接方式,查询表数据量分布、索引等,再结合单表的策略选择合适的关键字。 

mysql 实战 or、in与union all 的查询效率的更多相关文章

  1. mysql 中合并查询结果union用法 or、in与union all 的查询效率

    mysql 中合并查询结果union用法 or.in与union all 的查询效率 (2016-05-09 11:18:23) 转载▼ 标签: mysql union or in 分类: mysql ...

  2. ( 转 ) mysql 实战 or、in与union all 的查询效率

    OR.in和union all 查询效率到底哪个快. 网上很多的声音都是说union all 快于 or.in,因为or.in会导致全表扫描,他们给出了很多的实例. 但真的union all真的快于o ...

  3. SqlServer和MySql允许脏读的实现方式,提高查询效率

    --Sql Server 允许脏读查询sqlselect * from category with(nolock) --MySql 允许脏读查询sql Mysql没有语法糖,需要原生的sqlSET S ...

  4. mysql实战之 批量update

    mysql实战之批量update 现阶段我们的业务量很小,要对admin_user表中的relationship字段进行更新,指定id是409.已知409是公司内的一服务中心,需要把该服务中心放到区代 ...

  5. MySQL学习(五) UNION与UNION ALL

    UNION用于把来自许多SELECT语句的结果组合到一个结果集合中,也叫联合查询. SELECT ... UNION [ALL | DISTINCT] SELECT ... [UNION [ALL | ...

  6. centos mysql 实战 第一节课 安全加固 mysql安装

    centos mysql  实战  第一节课   安全加固  mysql安装 percona名字的由来=consultation 顾问+performance 性能=per  con  a mysql ...

  7. MySQL实战 | 04 为什么要使用索引?

    原文链接:MySQL实战 | 为什么要使用索引? 用过 MySQL 的应该都知道索引是干啥的吧,应该多少都设置过索引,但是若是问你索引是怎么实现的,你能说上来吗? 索引是什么? MySQL 官方对索引 ...

  8. mysql实战优化之一:sql优化

    1.选取最适用的字段属性 MySQL 可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得 ...

  9. MySQL实战 | 06/07 简单说说MySQL中的锁

    原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...

随机推荐

  1. 【Java EE 学习 30】【闪回】【导入导出】【管理用户安全】【分布式数据库】【数据字典】【方案】

    一.闪回 1.可能的误操作 (1)错误的删除了记录 (2)错误的删除了表 (3)查询历史记录 (4)撤销已经提交了的事务. 2.对应着以上四种类型的误操作,有四种闪回类型 (1)闪回表:将表回退到过去 ...

  2. 参数table_open_cache

    table_cache 参数设置表高速缓存的数目.每个连接进来,都会至少打开一个表缓存.因此, table_cache 的大小应与 max_connections 的设置有关.例如,对于 200 个并 ...

  3. Structs框架

    一.准备工作及实例 1.解压struts-2.1.6-all.zip(structs网上下载) apps目录:struts2自带的例子程序 docs目录:官方文档. lib 目录:存放所有jar文件. ...

  4. Hibernate的检索方式

    Hibernate的检索方式 检索方式(查询的方式) 导航对象图检索方式: 根据已经加载的对象导航到其他对象 Customer customer = (Customer)session.get(Cus ...

  5. Linux环境下的Nginx编译与安装

    1.新建文件夹: mkdir -p /zuker cd /zuker 2.编译: yum -y install gcc-c++ make wget autoconf libjpeg libjpeg-d ...

  6. NOIP2009多项式输出(水)【A004】

    [A004]潜伏者[难度A]—————————————————————————————————————————————————————————————————————————— [题目要求] 一元 n ...

  7. Spring任务调度之Timer

    一.分类 由于现在大部分的系统都是采用了spring,所以所有的例子都结合spring来构建,目前主要的任务调度分为三种: Java自带的java.util.Timer类,这个类允许你调度一个java ...

  8. 洛谷 P2737 [USACO4.1]麦香牛块Beef McNuggets Label:一点点数论 && 背包

    题目描述 农夫布朗的奶牛们正在进行斗争,因为它们听说麦当劳正在考虑引进一种新产品:麦香牛块.奶牛们正在想尽一切办法让这种可怕的设想泡汤.奶牛们进行斗争的策略之一是“劣质的包装”.“看,”奶牛们说,“如 ...

  9. python序列

    序列基础 序列:python包含6种内建的序列,常用的有:列表.元组.字符串.列表可以修改,元组和字符串不能修改. 索引:从0开始递增,通过索引获取元素:可使用负数索引,从右至左.最后1个元素的位置编 ...

  10. jsp页面取得一对多中的set集合的size

    jsp中使用${list.size }会编译成list.getSize()方法,并不能获取list的长度,因为程序回去找List对象中的getSize()方法,所以只能想别的办法, 一种方法是在后台程 ...