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

2023-06-02,,

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

(2016-05-09 11:18:23)
转载

标签:

mysql

union

or

in

分类:
mysql

问题一 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

赠金笔

阅读(1906)
评论 (0) 收藏(0)
转载(0)
喜欢
打印举报

已投稿到:

排行榜

转载列表:

转载

转载是分享博文的一种常用方式...

前一篇:msyql 百分比表示,mysql 表示null,mysql将一张表的查询结果存到另一张表中
后一篇:MySQL中distinct和group by性能比较

评论

重要提示:警惕虚假中奖信息

[发评论]

做第一个评论者吧! 抢沙发>>

点击加载更多

发评论

更多>>

登录名: 密码: 找回密码 注册 记住登录状态

昵   称:

评论并转载此博文

<!--
匿名评论

-->

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

< 前一篇msyql 百分比表示,mysql 表示null,mysql将一张表的查询结果存到另一张表中
后一篇 >MySQL中distinct和group by性能比较

mysql 中合并查询结果union用法 or、in与union all 的查询效率的相关教程结束。

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

下载本文的Word格式文档,以方便收藏与打印。