mysql 中合并查询结果union用法 or、in与union all 的查询效率
问题一 mysql
中合并查询结果union用法
今天来写写union的用法及一些需要注意的。
union:联合的意思,即把两次或多次查询结果合并起来。
要求:两次查询的列数必须一致
推荐:列的类型可以不一样,但推荐查询的每一列,想对应的类型以一样
可以来自多张表的数据:多次sql语句取出的列名可以不一致,此时以第一个sql语句的列名为准。
如果不同的语句中取出的行,有完全相同(这里表示的是每个列的值都相同),那么union会将相同的行合并,最终只保留一行。也可以这样理解,union会去掉重复的行。
如果不想去掉重复的行,可以使用union all。
如果子句中有order
by,limit,需用括号()包起来。推荐放到所有子句之后,即对最终合并的结果来排序或筛选。
如:(select * from a order by id) union (select * from b order
id);
在子句中,order by
需要配合limit使用才有意义。如果不配合limit使用,会被语法分析器优化分析时去除。
问题二 OR、in和union
all 查询效率到底哪个快。
OR、in和union all 查询效率到底哪个快。
网上很多的声音都是说union all 快于 or、in,因为or、in会导致全表扫描,他们给出了很多的实例。
但真的union all真的快于or、in?本文就是采用实际的实例来探讨到底是它们之间的效率。
1:创建表,插入数据、数据量为1千万【要不效果不明显】。
- drop table if EXISTS BT;
- create table BT(
- ID int(10) NOT NUll,
- VName varchar(20) DEFAULT '' NOT NULL,
- PRIMARY key( ID )
- )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 。
- DROP PROCEDURE IF EXISTS test_proc;
- CREATE PROCEDURE test_proc()
- BEGIN
- declare i int default 0;
- set autocommit = 0;
- while i<10000000 do
- INSERT INTO BT ( ID,VNAME ) VALUES( i, CONCAT( 'M', i ) );
- set i = i+1;
- if i
00 = 0 then - commit;
- end if;
- end while;
- END;
就不写注释呢,挺简单的。
存储过程是最好设置下innob的相关参数【主要和日志、写缓存相关这样能加快插入】,俺没有设置插入1千万条数据插了6分钟。
部分数据如下:1千万数据类似
中合并查询结果union用法 or、in与union all 的查询效率">
2:实战
2.1 :分别在索引列上使用 or、in、union all
我们创建的表只有主键索引,所以只能用ID做查询呢。我们查 ID 为 98,85220,9888589的三个数据各个耗时如下:
中合并查询结果union用法 or、in与union all 的查询效率" action-data="http%3A%2F%2Fdl.iteye.com%2Fupload%2Fattachment%2F389531%2Fa342480d-591e-3b7c-aebd-b00d98f9850a.jpg" action-type="show-slide">
时间都为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用法 or、in与union all 的查询效率" action-data="http%3A%2F%2Fdl.iteye.com%2Fupload%2Fattachment%2F389557%2F1f658995-93e7-3737-9cee-b2390512a70a.jpg" action-type="show-slide">
我们发现为啥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。
如以下查询:
- select * from bt where bt.VName = 'M98' or bt.id ='9888589'
- select * from bt where bt.VName = 'M98'
- UNION ALL
- select * from bt where bt.id = '9888589'
该两个查询速度相差多少 主要取决于 索引列查询时长,如索引列查询时间太长的话,那你也用or或者in代替吧。
3.5:
以上主要针对的是单表,而多表联合查询来说,考虑的地方就比较多了,比如连接方式,查询表数据量分布、索引等,再结合单表的策略选择合适的关键字。
2
喜欢
0
赠金笔
-->
0
赠金笔
转载列表:

转载是分享博文的一种常用方式...
- 做第一个评论者吧!
抢沙发>>
mysql 中合并查询结果union用法 or、in与union all 的查询效率的更多相关文章
- MySQL中case when的基本用法总结
MySQL中case when的基本用法总结原创Backcanhave7 最后发布于2018-12-06 15:14:15 阅读数 439 收藏展开MySQL中的case when有用两种用法,官方文 ...
- mysql中isnull,ifnull,nullif的用法
今天用到了MySql里的isnull才发现他和MSSQL里的还是有点区别,现在简单总结一下: mysql中isnull,ifnull,nullif的用法如下: 1. isnull(expr) 的用法: ...
- MySQL 中now()时间戳用法
MySQL 中now()时间戳用法 UPDATE news set addtime = unix_timestamp(now()); #结果:1452001082
- MySQL中索引和优化的用法总结
1.什么是数据库中的索引?索引有什么作用? 引入索引的目的是为了加快查询速度.如果数据量很大,大的查询要从硬盘加载数据到内存当中. 2.InnoDB中的索引原理是怎么样的? InnoDB是Mysql的 ...
- mysql中的group_concat函数的用法
本文通过实例介绍了MySQL中的group_concat函数的使用方法,比如select group_concat(name) . MySQL中group_concat函数 完整的语法如下: grou ...
- MySQL中 while loop repeat 的用法
-- MySQL中的三中循环 while . loop .repeat 求 1-n 的和 -- 第一种 while 循环 -- 求 1-n 的和 /* while循环语法: while 条件 DO 循 ...
- mysql中concat 和 group_concat()的用法
一.CONCAT()函数CONCAT()函数用于将多个字符串连接成一个字符串.使用数据表Info作为示例,其中SELECT id,name FROM info LIMIT 1;的返回结果为+----+ ...
- MySQL中change与modify的用法与区别
浅析MySQL中change与modify的区别 MySQL版本 show variables like 'version'; 表结构 desc student; 修改表 例如:修改表studen ...
- mysql中的if条件语句用法
· IF(expr1,expr2,expr3) 如果 expr1 是TRUE (expr1 <> 0 and expr1 <> NULL),则 IF()的返回值为expr2; ...
随机推荐
- CF 578B "Or" Game
传送门 解题思路 题意大概是给你一个数列,可以进行k次操作,每次操作可以选择一个数乘x,问操作后的或的最大值.根据位运算,位数越高答案越优,所以贪心的使这k次操作全都放到一个数上,这样的结果肯定较优. ...
- PhpExcel参考网址
参考网址: http://www.cnblogs.com/yuwensong/p/3771787.html
- 读书笔记--Hibernate in Action 目录
1.理解对象/关系持久化 2.启动项目 3.领域模型和元数据 4.映射持久化类 5.继承和定制类型 6.映射集合和实体关联 7.高级实体关联映射 8.遗留数据库和定制SQL 9.使用对象 10.事务和 ...
- mybatis深入理解(七)-----MyBatis缓存机制的设计与实现
缓存设计 MyBatis将数据缓存设计成两级结构,分为一级缓存.二级缓存: 一级缓存是Session会话级别的缓存,位于表示一次数据库会话的SqlSession对象之中,又被称之为本地缓存.一级缓存是 ...
- springmvc 支持对象与json 自动转换的配置
基于maven的工程, 需要在pom.xml中添加如下依赖 <dependency> <groupId>javax.servlet</groupId> <ar ...
- 在Spring应用中创建全局获取ApplicationContext对象
在Spring应用中创建全局获取ApplicationContext对象 1.需要创建一个类,实现接口ApplicationContextAware的setApplicationContext方法. ...
- xor
xor 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他语言1048576K 64bit IO Format: %lld 题目描述 Your are given n ...
- 洛谷P1569属牛的抗议 超级强力无敌弱化版
P1569 [USACO11FEB]属牛的抗议Generic Cow Prote- 题目描述 约翰家的N头奶牛聚集在一起,排成一列,正在进行一项抗议活动.第i头奶牛的理智度 为Ai,Ai可能是负数.约 ...
- 提交方式get和post有什么区别
提交方式post和get有什么区别? (1)post是向服务器传送数据:get是从服务器上获取数据. (2)在客户端,get是把参数数据队列加到提交表单的ACTION属性所指的URL中,值和表单内各个 ...
- Codeforces 3D
题目链接 D. Least Cost Bracket Sequence time limit per test 1 second memory limit per test 64 megabytes ...