使用 BETWEEN 子句和使用 <= 和 >= 比较之间是否存在性能差异?
即这两个查询:
SELECT *
FROM table
WHERE year BETWEEN '2005' AND '2010';
...和SELECT *
FROM table
WHERE year >= '2005' AND year <= '2010';
在这个例子中,年份列是VARCHAR2(4),并且有一个索引。
使用 BETWEEN 子句和使用 <= 和 >= 比较之间是否存在性能差异?
即这两个查询:
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
。
>=
和<=
来明确测试。 - Nicholas CareySQL Server 2000
。也不可能是共享 Sybase
代码库的 SQL Server 4.21
。因此,它必须是 6.0
、6.5
或 7.0
,在这些版本中,他们引入了标准违规行为,只为在 2000
年修复它(而没有提供向后兼容性,甚至在文档中提到此行为)。虽然我并不怀疑你的话,但这对于一个微软产品来说确实很奇怪。 - Quassnoi这两个示例查询没有性能差异,因为 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
实际上这取决于您的数据库管理系统引擎。
一些数据库管理系统将计算两次您的表达式(每个比较一次),而仅在使用 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
运行1 "X>=Y AND X<=Z"
运行2 "X BETWEEN Y AND Z"
当我运行两次解释计划时,我得到一个计划哈希值
。
但是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
可能会与标准的 >= 和 <= 组合有不同的执行计划。
显然,买家自负。但由于执行计划可能随时间而变化,而且我真的没有兴趣测试这些东西,所以我宁愿根本不使用BETWEEN。
有时候,选择少一点更好。
'2005'
这样的字符串来过滤年份或日期。 - Petrus Theron