使用 BETWEEN 子句或使用 <= AND >= 比较之间是否存在性能差异?
即这两个查询:
SELECT *
FROM table
WHERE year BETWEEN '2005' AND '2010';
...和
SELECT *
FROM table
WHERE year >= '2005' AND year <= '2010';
在此示例中,年份列是 VARCHAR2(4),其上有索引。
没有什么区别。
请注意,
BETWEEN
始终是包容性的并且对参数的顺序敏感。
BETWEEN '2010' AND '2005'
永远不会是TRUE
。
两个示例查询之间没有性能差异,因为
BETWEEN
只是表达 inclusive 范围比较的简写方式。当 Oracle 解析 BETWEEN
条件时,它会自动扩展为单独的比较子句:
例如。
SELECT *
FROM table
WHERE column BETWEEN :lower_bound AND :upper_bound
...会自动变成:
SELECT *
FROM table
WHERE :lower_bound <= column
AND :upper_bound >= column
可以通过检查解释计划来验证此行为。在这种情况下,两个查询将生成相同的解释计划,并且都将显示用于过滤结果的相同表达式:
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("YEAR"<='2010' AND "YEAR">='2005')
实际上这取决于您的 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
如果您的表达式是(例如)子查询,这可能会非常耗时。
当有疑问时(无论如何对于 Oracle),运行一个 解释计划,您将看到优化器想要做什么。 这适用于大多数有关“...之间是否存在性能差异”的问题。 当然还有很多其他工具,但解释计划是一个好的开始。
它应该是一样的。
好的数据库引擎将为该表达式生成相同的计划。
可能值得考虑一下 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 这里提到的那样
发现于http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
run1“X>=Y 和 X<=Z"
run2“Y 和 Z 之间的 X”
当我运行解释计划两次时,我得到一个
Plan hash value
。
但是 Tom 的 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%
您最好检查您的执行计划,因为可能存在一些奇怪的边缘情况,其中
BETWEEN
可能具有与标准 >= 和 <= combination. 不同的执行计划
买者自负显然。但由于执行计划可能会随着时间的推移而改变,而且我真的没有兴趣测试这些东西,所以我根本不使用 BETWEEN。
有时选择越少越好。