【问题标题】:BETWEEN clause versus <= AND >=BETWEEN 子句与 <= 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' 这样的字符串来过滤年份或日期。

标签: sql performance oracle oracle10g oracle11g


【解决方案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。

        有时选择越少越好。

        【讨论】:

          猜你喜欢
          • 2016-11-04
          • 2019-08-31
          • 1970-01-01
          • 1970-01-01
          • 2012-06-18
          • 2012-01-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多