BETWEEN 子句与 <= AND >=
Posted
技术标签:
【中文标题】BETWEEN 子句与 <= AND >=【英文标题】:BETWEEN clause versus <= AND >= 【发布时间】:2011-06-16 02:18:51 【问题描述】:使用 BETWEEN 子句或使用 = 比较之间是否存在性能差异?
即这两个查询:
SELECT *
FROM table
WHERE year BETWEEN '2005' AND '2010';
...和
SELECT *
FROM table
WHERE year >= '2005' AND year <= '2010';
在本例中,年份列是 VARCHAR2(4),上面有一个索引。
【问题讨论】:
不过,我不会使用像'2005'
这样的字符串来过滤年份或日期。
【参考方案1】:
没有区别。
请注意,BETWEEN
始终包含且对参数的顺序敏感。
BETWEEN '2010' AND '2005'
永远不会是TRUE
。
【讨论】:
取决于底层的 RDBMS 系统。 SQL-92 说 "X BETWEEN Y AND Z" 等价于 "X>=Y AND X,但并非所有供应商都遵守这一行。例如,SQL Server 就没有。 @Nicholas:请看问题标签。至于你SQL Server
的评论,能否提供参考?
除非他们在两者之间收紧,否则顺序并不重要。不过,不能说我最近测试过。之前已经被烧毁了,如果顺序对测试很重要,我会使用>=
和<=
进行显式测试。
@Nicholas:你是说有一个版本的SQL Server
将3 BETWEEN 4 AND 2
评估为TRUE
?
@Nicholas:你能说出这个版本的名字吗?【参考方案2】:
两个示例查询之间没有性能差异,因为BETWEEN
只是表达包含范围比较的简写方式。当 Oracle 解析 BETWEEN
条件时,它会自动展开成单独的比较子句:
例如
SELECT *
FROM table
WHERE column BETWEEN :lower_bound AND :upper_bound
...会自动变成:
SELECT *
FROM table
WHERE :lower_bound <= column
AND :upper_bound >= column
【讨论】:
@rsenna:不,我发布这个问题是为了在此处存储信息,因为我们办公室的某个人问过我这个问题,我在搜索时注意到以前没有人在这里问过这个问题。这是我今天对世界的知识贡献,并且是根据常见问题解答和使命声明对服务的有效使用。我本打算在 10 秒内全部提问、回答并接受我的回答,但系统不允许我这么快接受我自己的回答,所以其他人也开始回答...... 嘿,没问题。事实上SO官方approves这样的行为... @rsenna:没错! :) 感谢您挖掘该链接,并进一步解释我忘记您必须 wait two days to answer your own question... 我个人不同意徽章的存在,因为我所看到的只是人们试图通过游戏系统来获取它(在发布问题后的几分钟内将已知答案发布到副本) .更糟糕的是那些接受自己的人胜过在他们面前正确回答的人。我永远不会通过投票给这样的答案来启用这种行为。【参考方案3】:其实这取决于你的 DBMS 引擎。
一些数据库管理系统会计算两次您的表达式(每次比较一次),并且在您使用 BETWEEN
时只计算一次。
实际上如果表达式可以有一个不确定的结果BETWEEN
会有不同的行为,在SQLite中比较以下:
WHERE RANDOM() BETWEEN x AND y -- one random value generated
WHERE RANDOM() >= x AND RANDOM() <= y -- two distinct random values generated
如果您的表达式是(例如)子查询,这可能会非常耗时。
【讨论】:
有趣的想法...你能提供一个例子吗?您对哪个数据库有过这种体验? 嗯,好主意。这留下了一些关于SQL standard 的悬而未决的问题,以及是否真的有可能声称这两个表达式是等价的【参考方案4】:如果有疑问(无论如何对于 Oracle),运行explain plan,您就会看到优化器想要做什么。这将适用于大多数关于“...之间是否存在性能差异”的问题。当然还有很多其他的工具,但是解释计划是一个好的开始。
【讨论】:
【参考方案5】:应该是一样的。
良好的数据库引擎将为该表达式生成相同的计划。
【讨论】:
是的,我的评论比这种具体情况更笼统。教人钓鱼……【参考方案6】:可能值得考虑这方面的 SQL 标准(尽管这个可能不对应于所有实现,即使它应该):
Format
<between predicate> ::=
<row value constructor> [ NOT ] BETWEEN
<row value constructor> AND <row value constructor>
Syntax Rules
[...]
6) "X BETWEEN Y AND Z" is equivalent to "X>=Y AND X<=Z".
话虽如此,但行为上没有区别,虽然对于复杂的X
,解析时间可能会有所不同,正如Benoit here所提到的那样
发现于http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
【讨论】:
【参考方案7】:run1 "X>=Y AND X
run2 "X BETWEEN Y AND Z"
当我运行两次解释计划时,我得到一个Plan hash value
。
但是汤姆的 runStats_pkg 得到不同的结果:
Run1 ran in 1 cpu hsecs
Run2 ran in 1 cpu hsecs
run 1 ran in 100% of the time
Name Run1 Run2 Diff
STAT...recursive calls 12 13 1
STAT...CPU used by this sessio 2 3 1
STAT...physical read total IO 0 1 1
STAT...consistent gets 18 19 1
...
...
LATCH.row cache objects 44,375 1,121 -43,254
LATCH.cache buffers chains 68,814 1,397 -67,417
STAT...logical read bytes from 655,360 573,440 -81,920
STAT...session uga memory max 123,512 0 -123,512
STAT...session pga memory 262,144 65,536 -196,608
STAT...session pga memory max 262,144 65,536 -196,608
STAT...session uga memory -327,440 65,488 392,928
Run1 latches total versus runs -- difference and pct
Run1 Run2 Diff Pct
203,927 28,673 -175,254 711.22%
【讨论】:
【参考方案8】:您最好检查一下您的执行计划,因为可能会出现一些奇怪的边缘情况,BETWEEN
的执行计划可能与标准的 >= 和
https://blog.pythian.com/oracle-can-between-and-greater-than-or-equal-to-and-less-than-or-equal-to-differ/
显然是买者自负。但是由于执行计划会随着时间而改变,而且我真的没有兴趣测试这些东西,所以我宁愿完全不使用 BETWEEN。
有时选择越少越好。
【讨论】:
以上是关于BETWEEN 子句与 <= AND >=的主要内容,如果未能解决你的问题,请参考以下文章