新足迹

 找回密码
 注册

精华好帖回顾

· 两机三镜,再战纽西兰 (2012-4-14) 老陶 · 资深潜水员冒泡--家常菜系列@煎酿三宝之看图说话(23楼补充了鱼滑的打制方法) (2011-8-8) Quantum
· 良辰美景-戊戌维新百年乱弹[原创] (2005-4-30) jeru · 猎梦人 谈关于外汇公司的讨论 (2010-6-11) 猎梦人
Advertisement
Advertisement
查看: 2503|回复: 36

求解释SQL Union VS OR [复制链接]

发表于 2012-3-14 14:39 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
有段SQL 代码大约是

select xxxx from yyy
where conditionA or conditionB,

运行时间大约10
---------------------------------------------
如果把or 改为union

select xxxx from yyy
where conditionA
union
select xxxx from yyy
where conditionB,
运行时间大约1
------------------------------------------
为什么会这样??

评分

参与人数 1积分 +3 收起 理由
atransformer + 3 真的假的?

查看全部评分

Advertisement
Advertisement

发表于 2012-3-14 14:41 |显示全部楼层
此文章由 红烧鸡翅 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 红烧鸡翅 所有!转贴必须注明作者、出处和本声明,并保持内容完整
or 用的时间是 a*b
union用的时间是 a+b

评分

参与人数 1积分 +2 收起 理由
+ 2 也许?

查看全部评分

发表于 2012-3-14 14:57 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
回复atransformer
这是真的,来自我们的产品环境

我在tunning一段别人写的SQL代码, 原来要50秒,凭直觉不应该,
改写后依然要10秒,觉得还是不对,

然后把or condition分开运行发现很快,才想到用union, 结果不到1秒

网上有人在问同样的问题,好像目前没有答案。还有人坚持不相信有这回事

[ 本帖最后由 典 于 2012-3-14 13:58 编辑 ]

发表于 2012-3-14 15:17 |显示全部楼层
此文章由 wil 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 wil 所有!转贴必须注明作者、出处和本声明,并保持内容完整
上execution plan就好解释了

评分

参与人数 2积分 +3 收起 理由
+ 2 谢谢奉献
fyang1024 + 1 正道

查看全部评分

发表于 2012-3-14 15:38 |显示全部楼层
此文章由 杨白劳 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 杨白劳 所有!转贴必须注明作者、出处和本声明,并保持内容完整
1) I believe the sample using "OR" might prevent the use of index. It is hard to say without the actual SQL and table design. How about putting both conditions into brackets?

SELECT xxx FROM yyy Where (Cond 1) OR (Cond 2)

2) If the table is large, it is quick to scan the index twice then scanning the entire table once.

3) Usually it is not recommended to use UNION where you can avoid.

评分

参与人数 1积分 +2 收起 理由
+ 2 谢谢奉献

查看全部评分

发表于 2012-3-14 15:55 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
我在1楼说的是简化后的情况,实际的Query有点点复杂,涉及到很多表和sub-query

看了execution plan, 有个表发现分开运行时(union情况下)index seek,
                                   用or合并时, 变成了index scan,
                                
                                 也许这是原因所在。

这应该是特例,用其它一些query来检验,没有发现union 比 or 快
Advertisement
Advertisement

发表于 2012-3-14 16:50 |显示全部楼层
此文章由 fyang1024 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 fyang1024 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 wil 于 2012-3-14 15:17 发表
上execution plan就好解释了


用Oracle 10测了一下, Union比Or慢

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
八个避孕套

参与宝库编辑功臣

发表于 2012-3-14 17:39 |显示全部楼层
此文章由 bffbffbff 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 bffbffbff 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 于 2012-3-14 15:55 发表
我在1楼说的是简化后的情况,实际的Query有点点复杂,涉及到很多表和sub-query

看了execution plan, 有个表发现分开运行时(union情况下)index seek,
                                   用or合并时, 变成了index scan,
...


不算是很特的例, 起码我遇见好几次了, 我觉得 index scan v index seek 的说法有一定道理
永远的junior programmer

发表于 2012-3-14 18:29 |显示全部楼层

回复 典 1# 帖子

此文章由 marklan001 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 marklan001 所有!转贴必须注明作者、出处和本声明,并保持内容完整
那个union不用 Select Distinct?

参与宝库编辑功臣

发表于 2012-3-14 21:05 |显示全部楼层
此文章由 bffbffbff 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 bffbffbff 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 marklan001 于 2012-3-14 18:29 发表
那个union不用 Select Distinct?


有 union 就不用 distinct 了
永远的junior programmer
头像被屏蔽

禁止访问

发表于 2012-3-14 21:12 |显示全部楼层
此文章由 atransformer 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 atransformer 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 于 2012-3-14 14:57 发表
回复atransformer
这是真的,来自我们的产品环境

我在tunning一段别人写的SQL代码, 原来要50秒,凭直觉不应该,
改写后依然要10秒,觉得还是不对,

然后把or condition分开运行发现很快,才想到用union, 结果不到1秒

网上有人在问同样的问题,好像目前没有答案。还有人坚持不相信有这回事


你的条件列有没有index?
Advertisement
Advertisement

发表于 2012-3-14 21:21 |显示全部楼层
此文章由 Fernando 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 Fernando 所有!转贴必须注明作者、出处和本声明,并保持内容完整
还是拿具体的table,index,statistics,放到具体的数据库版本里面说吧

发表于 2012-3-14 21:27 |显示全部楼层
此文章由 huaxianz 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 huaxianz 所有!转贴必须注明作者、出处和本声明,并保持内容完整
execution plan说明了一切。

发表于 2012-3-14 21:29 |显示全部楼层
此文章由 wendy 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 wendy 所有!转贴必须注明作者、出处和本声明,并保持内容完整
did you flash out the buffer cache before you run the second statement?

发表于 2012-3-14 21:32 |显示全部楼层
此文章由 NNX 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 NNX 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 wendy 于 2012-3-14 21:29 发表
did you flash out the buffer cache before you run the second statement?


同感, 可能只是cache的原因

发表于 2012-3-14 22:19 |显示全部楼层
此文章由 huaxianz 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 huaxianz 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 wendy 于 2012-3-14 21:29 发表
did you flash out the buffer cache before you run the second statement?


我猜楼主是在production环境下,cache flushing可能不适合。

我脚着index/table scan还是index seek多数取决于selectivity.如果condition A和condition B都分别低于threshold,query optimizer当然选择bookmark lookup,这是个union的情形;但如果condition A + condition B超过了那个threshold,query optimizer则认为table/index scan的cost更低,这个就是or的情形。当然都是理论,实际情况就像前面有人说过的,离不开具体的physical characteristics of table, index, statistics,甚至是server runtime尤其是severity of memory pressure. memory pressure是决定前面谈到的threshold因素之一。

还是那句话,execution plan talks.

评分

参与人数 1积分 +2 收起 理由
fyang1024 + 2 我很赞同

查看全部评分

Advertisement
Advertisement

发表于 2012-3-14 22:21 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
1) Cache应该没问题, 两个query反复运行,连续运行多次,结果都一样
2) 确实两个query的exec plan 完全不一样, 结构都变了,连比较都不太好比,
同意大家的意见, exec plan说明一切, 明天看能不能贴出来给大家研究
包括io / time statistics
3) 在另外一台SQL 2008服务器上测试,几乎是产品数据库的镜像,则没有这个问题。
4) 准备从逻辑上从新设计这段程序,有把握进一步降低到0.1秒左右,对query本身我准备放弃优化了

发表于 2012-3-14 22:26 |显示全部楼层

回复 bffbffbff 8# 帖子

此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
请问你碰到这种情况后如何处理? 用union 代?

发表于 2012-3-14 22:46 |显示全部楼层
此文章由 waynepublic 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 waynepublic 所有!转贴必须注明作者、出处和本声明,并保持内容完整
这个情况我们也碰到几回,和clean buffer没有关系。在这种情况下,or会导致sql server无法用一个index完成query,于是认为一个table scan或index scan优于两个index seek。sql server在选择index plan时不是每次都是明智的。楼主可以set io statistics on来比较一下各读了多少page。

发表于 2012-3-14 22:59 |显示全部楼层

回复 waynepublic 19# 帖子

此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
有没有简单的解决办法?
我试了forceseek 来强制使用seek
没有效果,也许测试的table不对

发表于 2012-3-14 23:04 |显示全部楼层
此文章由 Janet 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 Janet 所有!转贴必须注明作者、出处和本声明,并保持内容完整
condition A or B 是有Index过滤吗?

如果没有index 的话,应该不会差这么多吧
Advertisement
Advertisement

参与宝库编辑功臣

发表于 2012-3-15 10:17 |显示全部楼层
此文章由 bffbffbff 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 bffbffbff 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 于 2012-3-14 22:26 发表
请问你碰到这种情况后如何处理? 用union 代?


我也没啥好的方法,也没怎么研究,union可以解决的就用union了,然后就是写query的时候用or的时候一般都比较小心,尤其是大点的query。
目前观察到的(当然样本有限可能结论不对)union 比 or 差距明显(和你说的差不多是10几秒甚至几十秒 v 几秒的区别)的2个主要特征:

1. 和花仙子说的类似,selectivity很有关系,如果or左右的两个condition中的一个以上会返回非常多的数据,一般会有问题 极端的例子: col1 is not null 之类
2. 问题一般出现在or的两个condition都是直接对1个或多个表进行seek/scan。 如果有一个condition是个variable比较(@isEnabled=1), 只有另一个condition在做查询, 一般不会有问题
永远的junior programmer

发表于 2012-3-15 10:33 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
使用Or的时候

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

发表于 2012-3-15 10:35 |显示全部楼层

使用Union的时候

此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
使用Union的时候

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

发表于 2012-3-15 10:38 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
可能真是2楼说的,使用OR的时候, work table的scan次数爆增。

Plan则不太好比,因为结构完全变了。

不过这个query设计得很不好,虽然改了一次提高了几十倍的速度,但是依然不合理,准备有空的时候推倒重来。

发表于 2012-3-15 15:49 |显示全部楼层
此文章由 huaxianz 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 huaxianz 所有!转贴必须注明作者、出处和本声明,并保持内容完整
我的直觉是第一张plan的精华在图的左半部。。。什么导致index spool?是不是下面分支处在另外一个Nested Loops的outer side?比如上面分支返回100行的话,则下边rowset要被rewound100回。。。index/table spool不需要重新读原表,数据被暂时的(within query scope) dump到tempdb上,所以rewind对tempdb有很大的negative impact. 第二张图的hash match则不存在这个问题。所以问题的焦点从index scan转移到了index spool。

评分

参与人数 1积分 +3 收起 理由
+ 3 我很赞同

查看全部评分

Advertisement
Advertisement

发表于 2012-3-15 15:52 |显示全部楼层
此文章由 huaxianz 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 huaxianz 所有!转贴必须注明作者、出处和本声明,并保持内容完整
向网警致敬~

发表于 2012-3-15 15:58 |显示全部楼层
此文章由 porcorosso 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 porcorosso 所有!转贴必须注明作者、出处和本声明,并保持内容完整
个人觉得OR比较可取,UNION是当两个queries的source不一样时才用的

[ 本帖最后由 porcorosso 于 2012-3-15 16:00 编辑 ]

发表于 2012-3-20 21:38 |显示全部楼层

回复 典 17# 帖子

此文章由 remonyan 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 remonyan 所有!转贴必须注明作者、出处和本声明,并保持内容完整
我说两点看法:
1。你第三点的现象说明你的index/ststistics己经outdate了,估计没做常规的maintenance
2。从23#和24#公布的I/O stats来看,没有physical reads, 证明你的测试都是在cache里进行的,这样似乎对实际prod issue没啥参考价值。除非你的库很小而RAM极大且系统不忙。
欢迎探讨
吃自钓的鱼,喝自酿的酒,爽!

发表于 2012-3-21 11:01 |显示全部楼层
此文章由 典 原创或转贴,不代表本站立场和观点,版权归 oursteps.com.au 和作者 典 所有!转贴必须注明作者、出处和本声明,并保持内容完整
原帖由 remonyan 于 2012-3-20 20:38 发表
我说两点看法:
1。你第三点的现象说明你的index/ststistics己经outdate了,估计没做常规的maintenance
2。从23#和24#公布的I/O stats来看,没有physical reads, 证明你的测试都是在cache里进行的,这样似乎对实际prod issue没啥参考价值。除非你的库很小而RAM极大且系统不忙。
欢迎探讨


你很仔细..确实数据库不大200G左右, RAM很大20G,系统不会很忙只有几百user,且只用于transaction,所以经常情况下没有physical read...

发表回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Advertisement
Advertisement
返回顶部