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的评论,能否提供参考? 除非他们在两者之间进行了收紧,否则顺序并不重要。不过,不能说我最近测试过。之前已经被烧毁了,如果顺序对测试很重要,我会使用&gt;=&lt;= 进行显式测试。 @Nicholas:你是说有一个版本的SQL Server3 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 >=的主要内容,如果未能解决你的问题,请参考以下文章

5.WHERE 子句

SQL WHERE 子句

Hibernate

SQL Where 子句详解

SQL WHERE 子句

SQL WHERE 子句