代码之家  ›  专栏  ›  技术社区  ›  Scott

常量上的空值替换

  •  2
  • Scott  · 技术社区  · 15 年前

    为了好玩,我今天一直在玩内置的甲骨文优化在蟾蜍。它建议的优化之一是

    AND emp.pay_type = NVL('FT', UID)
    

    而不是

    AND emp.pay_type = 'FT'
    

    我对这里发生的事情感到困惑,也对为什么这会提高性能感到困惑。既然ft是SQL查询中的一个字符串文本,因此从不为空,为什么这会有什么区别呢?我猜想这与字段上现有的索引有关,但在Oracle文档中找不到任何内容。

    3 回复  |  直到 15 年前
        1
  •  4
  •   Jonathan Leffler    15 年前

    这是个奇怪的建议。nvl函数的工作方式如下:

    NVL(exp1, val1)
    

    如果“exp1”不为空,则返回它;否则返回“val1”。

    由于示例中的“ft”不能为空,因此使用nvl函数没有任何好处,并且性能损失较小(至少对于优化器来说,计算出nvl是冗余的;如果优化器不计算出nvl是冗余的,则可能是执行损失)。

    如果条件为:

    和emp.pay_type=nvl(“ft”,uid)

    那么可能会有好处;这里我们有一个分隔标识符(用双引号括起来的列名),列值可能为空;nvl调用确保只有当“ft”为空时才返回空值。 UID为空。当然,uid是一个常规标识符。

    如果条件为:

    AND emp.pay_type = NVL(UID, 'FT')
    

    现在,如果uid值为空,则使用默认值“ft”作为相应的付薪类型。

        2
  •  3
  •   Jeffrey Kemp    15 年前

    我会接受蟾蜍的“优化建议”和大粒的盐。我称之为“猎枪”优化方法——以某种方式向目标发射大量不同的子弹,然后看看哪一个击中了目标。)

    不管怎样,两者之间的区别

    AND emp.pay_type = NVL('FT', UID)
    

    AND emp.pay_type = 'FT'
    

    在第二种情况下,优化器可以使用列上的柱状图统计信息(如果已经收集了它们)来获得匹配行数的更准确估计。然而,当使用nvl时,优化器(我相信)不会检测到它可以忽略nvl,因此不会检查该值的柱状图。

    这不是我通常使用的优化方法。有更好的方法来控制查询的执行路径(例如提示)。特别是,如果改进CBO以查找和优化冗余代码,这种方法将失败 NVL([literal value],[anything]) [literal value] .

        3
  •  1
  •   DCookie    15 年前

    关于这两个查询,Oracle的解释计划告诉了您什么?