【问题标题】:What does +0 mean after an ORDER BY in OracleOracle ORDER BY 后的 +0 是什么意思
【发布时间】:2011-03-12 21:58:44
【问题描述】:

我试图理解这个 Oracle 9i 查询末尾的 +0 是什么意思:

SELECT /*+ INDEX (a CODE_ZIP_CODE_IX) */ 
       a.city, 
       a.state, 
       LPAD(a.code,5,0)  ZipCode, 
       b.County_Name     CoName, 
       c.Description     RegDesc, 
       d.Description     RegTypeDesc  
FROM TBL_CODE_ZIP a, 
     TBL_CODE_COUNTY b, 
     TBL_CODE_REGION c, 
     TBL_CODE_REGION_TYPE d  
WHERE a.City = 'LONDONDERRY' 
    AND a.State = 'NH' 
    AND lpad(a.Code,5,0) = '03038' 
    AND a.Region_Type_Code = 1 
    AND b.County(+) = a.County_Code  
    AND b.STATE(+) = a.STATE 
    AND c.Code(+) = a.Region_Code  
    AND d.Code(+) = a.Region_Type_Code  
ORDER BY a.Code +0

有什么想法吗?

注意:我认为这与升序或降序无关,因为我不能在 a.Code 和 +0 之间添加 asc 或 desc,我可以在 +0 之后添加 asc 或 desc

【问题讨论】:

  • 是不是通过导致隐式转换来强制a.Code变成数值数据类型?
  • a.Code 被指定为 NUMBER(5)
  • 一旦代码布局正确,事情就会变得更加清晰。
  • 是的,很抱歉。感谢 Niessner 正确格式化。

标签: sql oracle sorting oracle9i


【解决方案1】:

+ 0 在基于规则的优化器时代是一个技巧,它使得无法在数字列上使用索引。同样,他们为字母数字列做了|| ''

对于您的查询,我在检查后可以得出的唯一结论是它的创建者在性能方面遇到了困难。如果(这是我的假设)索引 CODE_ZIP_CODE_IX 是 TBL_CODE_ZIP(Code) 上的索引,那么即使提示使用它,查询也不会使用它。创建者可能不知道通过使用 LPAD(a.code,5,0) 而不是 a.code,无法使用索引。 order by 子句获取其中间结果集(驻留在内存中)并对其进行排序。不需要索引。但是对于+ 0,他似乎正在考虑禁用它。

因此,所使用的技巧无效,现在只是误导,正如您所发现的那样。

问候, 抢。

PS1:最好使用 LPAD(TO_CHAR(a.code),5,'0') 或 TO_CHAR(a.code,'fm00009')。然后很清楚你在用数据类型做什么。

PS2:您的查询可能会受益于在 LPAD(TO_CHAR(a.code),5,'0') 上使用基于函数的索引,或使用任何用于填充邮政编码的表达式。

【讨论】:

    【解决方案2】:

    我的猜测是 a.code 是一个包含数字字符串的 VARCHAR2,+0 有效地将其转换为 NUMBER,因此排序将是数字而不是 alpha

    您应该能够在 +0

    之后添加 ASC/DESC

    【讨论】:

    • @MarkBaker 代码是一个数字(5)......如果有帮助的话。但是,我能够在之后指定 asc 或 desc 并且它起作用了!
    • 似乎是一种奇怪的做法——这样做有没有好处,而不是仅仅使用to_number(a.code)
    • @FrustratedWithFormsDesigner - 写得更短?否则没有显着差异(除了使用 TO_NUMBER 进行格式化控制)。
    • @Lucas B - 如果 a.code 已经是 NUMBER 则 +0 是多余的
    • 谁能提供参考来证实 MarkBaker 的猜测?
    【解决方案3】:

    注意:我已经删除了这个答案,因为 Mark B 是更快的打字员。但是,我重新设置了它,因为我认为展示 Lucas 发布的 SQL 的潜在意图是有一些价值的。


    假设 CODE 是一个 VARCHAR2 列,其中包含数字字符串(邮政编码)。问题是 varchars 排序为字符串而不是数字。将零添加到 CODE 会产生对数字的隐式强制转换,因此按数字排序:

    SQL> select id, code
      2  from t72
      3  order by code
      4  /
    
            ID CODE
    ---------- -----
             1 1
             2 11
             3 111
             4 12
    
    SQL> select id, code
      2  from t72
      3  order by code+0
      4  /
    
            ID CODE
    ---------- -----
             1 1
             2 11
             4 12
             3 111
    
    SQL>
    

    如果存储的代码用零填充,则不需要强制转换,因为它们无论如何都会按数字顺序排序。

    正如其他人所观察到的,使用 TO_NUMBER() 会是更好的选择。 +0 没有显式强制转换那么明显,明确意图总是好的。

    【讨论】:

    • to_number(a.code)会不会有同样的效果,还是和+0有区别?
    • 我认为 to_number 会有同样的效果,对读者来说会更明显。
    【解决方案4】:

    TBL_CODE_ZIP.Code 上有索引吗?我已经看到将 0 添加到数字(或 '' 到字符串)的查询,以强制优化器避免对查询的该部分使用索引。 (当然,避免使用索引的正确方法是添加适当的提示)

    也许原作者遇到了一个问题,即 ORDER BY 被优化为索引扫描,导致查询运行速度变慢;所以他们添加了 +0 来强制使用不同的访问路径并进行普通排序。

    【讨论】:

    • 是的,有一个名为 CODE_ZIP_CODE_IX 的索引,其中包含一个.Code,在这个查询中,我们“暗示”使用该索引。当我通过解释计划查看它时,比较有和没有 +0 的计划是相同的。
    • @Lucas,是的,现在不一定会有所作为。或者,开发人员可能错误地认为这会使其更快,因为“它以前对我有用”:)
    • 我同意,我的一位同事认为这可能是 Oracle 8 实施的遗留问题。感谢您的洞察力。
    【解决方案5】:

    首先很抱歉回答,因为这是一个非常古老的问题。但是 +0 是提示您的数据库忽略此特定查询的索引(如果它在 a.Code 列上),

    根据数据库的优化器模式,有时索引会加快检索速度,而有时会很慢。

    所以现在您有两个选项,使用 +0 提示或删除索引,如果它在 a.code 上,您将获得相同的速度。

    【讨论】:

      猜你喜欢
      • 2021-07-17
      • 2015-03-20
      • 2020-01-07
      • 2018-09-10
      • 2021-06-11
      • 1970-01-01
      • 2017-05-09
      • 2018-09-25
      • 2011-05-25
      相关资源
      最近更新 更多