Spiga

MS SQL 技巧系列(二)SQL查询的性能大PK之:or vs. union

2010-03-18 12:06 by Virus-BeautyCode, 2216 visits, 收藏, 编辑

  在sql查询的where条件语句中,可以使用and和or实现逻辑的判断。如果where比较复杂的话,就会产生and 和 or的嵌套使用,写起来会很费力气,看起来就更是一头雾水了。

  于是有人就想起了union,其实它是可以替代or的,反正就是把结果串联起来,貌似应该可以。而且,写起来更加容易,看起来也很清晰。但是不知道两个的性能如何呢?下面我就做一个比较,建立三张表,分别插入10万,100万和1000万的数据,每张表格都有8个字段,然后在三种数据量下,做三个字段的or和union,五个字段的or和union,然后通过查询时间比较一下他们的效率吧。

  硬件环境:Q8200  4GB 内存

  操作系统:Windows2003 R2

  数据库:SQL SERVER 2005

代码
create database test
go
use test
go
--建立测试表1
create table table1
(
  col1 
varchar(20),
  col2 
varchar(20),
  col3 
varchar(20),
  col4 
varchar(20),
  col5 
varchar(20),
  col6 
varchar(20),
  col7 
varchar(20),
  col8 
varchar(20)
)
go
--插入10万数据
declare @i int
set @i=1
while(@i<100000)

  begin
    insert into table1 values('123','123','123','123','123','123','123','123')
    set @i=@i+1
  end

go
--建立测试表2
create table table2
(
  col1 
varchar(20),
  col2 
varchar(20),
  col3 
varchar(20),
  col4 
varchar(20),
  col5 
varchar(20),
  col6 
varchar(20),
  col7 
varchar(20),
  col8 
varchar(20)
)
go
--插入100万数据
declare @i int
set @i=1
while(@i<1000000)

  begin
    insert into table2 values('123','123','123','123','123','123','123','123')
    set @i=@i+1
  end

go
--建立测试表3
create table table3
(
  col1 
varchar(20),
  col2 
varchar(20),
  col3 
varchar(20),
  col4 
varchar(20),
  col5 
varchar(20),
  col6 
varchar(20),
  col7 
varchar(20),
  col8 
varchar(20)
)
go
--插入1000万数据
declare @i int
set @i=1
while(@i<1000000)

  begin
    insert into table3 values('123','123','123','123','123','123','123','123')
    set @i=@i+1
  end

go
--耗时4秒
select * from table1 
where col1='123' or col2='123' or col3='123' 
go
--耗时11秒
select * from table1
where col1='123' 
union all
select * from table1
where col2='123' 
union all
select * from table1
where col3='123' 
go
--耗时4秒
select * from table1 
where col1='123' or col2='123' or col3='123' or col4='123' or col5='123' 
go
--耗时19秒
select * from table1
where col1='123' 
union all
select * from table1
where col2='123' 
union all
select * from table1
where col3='123' 
union all
select * from table1
where col4='123' 
union all
select * from table1
where col5='123' 
go

--耗时37秒
select * from table2 
where col1='123' or col2='123' or col3='123' 
go
--耗时1分53秒
select * from table2
where col1='123' 
union all
select * from table2
where col2='123' 
union all
select * from table2
where col3='123' 
go
--耗时38秒
select * from table2 
where col1='123' or col2='123' or col3='123' or col4='123' or col5='123' 
go
--耗时2分24秒
select * from table2
where col1='123' 
union all
select * from table2
where col2='123' 
union all
select * from table2
where col3='123' 
union all
select * from table2
where col4='123' 
union all
select * from table2
where col5='123' 
go


drop table table1
drop table table2
drop table table3
drop database test

 

  从上面的可以看出来使用or和union连接where条件的话,数据10w和100w没有差距,只是在1000w的时候急速增大,但是同等数据量的话,使用or和union就表现了很大的差距,尽管union写起来和看起来都比较好理解。

  结论:我想是因为每次使用union都会扫描一次表结构,or虽然难些难看,但是只扫描一次表结构,所以数据量上去的话,就会体现出来更大的优势。

  结论仅供参考,欢迎大家一起讨论。

  刚才看见一篇极限挑战—100万条数据导入SQL SERVER数据库仅用4秒 (附源码),好文章,转载一下地址。感谢作者的无私分享。

【Blog】http://virusswb.cnblogs.com/

【MSN】jorden008@hotmail.com

【说明】转载请标明出处,谢谢

 

反馈文章质量,你可以通过快速通道评论:

Add your comment

11 条回复

  1. #1楼 killkill      2010-03-18 12:19
    最好贴出执行计划。
     回复 引用 查看   
  2. #2楼 Frank Xu Lei      2010-03-18 12:32
    路过,支持一下~
    呵呵。

    代码别收缩好看点,最后有对比数据就更有说服力啊
     回复 引用 查看   
  3. #3楼 阿水      2010-03-18 13:20
    执行计划和统计信息,贴出来就比较清楚了。
     回复 引用 查看   
  4. #4楼 Robin Zhang      2010-03-18 13:48
    http://www.cnblogs.com/mywebname/articles/554584.html
     回复 引用 查看   
  5. #5楼 Robin Zhang      2010-03-18 13:48
    http://www.cnblogs.com/mywebname/articles/554584.html
    这哥们的结果是union比or性能高
     回复 引用 查看   
  6. #6楼 寒 刚入门      2010-03-18 14:11
    这个结果是很明显的.
    在没有索引的情况下,一次表扫描的速度自然比三次扫描的速度快了.
    那是不是建了索引union就比or快了呢?
    不是的,由于这个测试的数据实在是太糟糕了.数据全都是一样的.
    数据库搜索引擎在这种情况下是不会用索引的,因为使用索引的开销会更大.
    如果数据中的值有几百条是"456".那么在大数据量的情况下.union肯定比or快很多.
     回复 引用 查看   
  7. #7楼 阿水      2010-03-18 14:19
    楼主的例子不是特别合适,应为以上情况大家写SQL的习惯应该是用IN.
    不会用UNION的。
    用UNION的情况大多是数据来自不同的表,否则谁会用UNION呀。
     回复 引用 查看   
  8. #8楼 wengda      2010-03-18 14:39
    为什么是union all 呢?应该用union吧。否则返回的数据总条数都不一样吧?
     回复 引用 查看   
  9. #9楼 blackcat      2010-03-18 15:44
    没有执行计划,都是白搭。
     回复 引用 查看   
  10. #10楼 OK_008      2010-03-18 23:08
    光从查询使用时间来判断优化是不合适的。

    很多时候需要从评估的Execution Plans &实际的Execution Plans,I/O,索引的使用,数据量的大小来确定如何优化。
     回复 引用 查看   
  11. #11楼[楼主] virus      2010-03-18 23:15
    感谢大家的参与,看来我的路还长呢,距离还是有的
     回复 引用 查看