为了好玩,我今天一直在玩Toad的内置Optimizer for Oracle。它建议的优化之一是以下
AND emp.pay_type = NVL('FT', UID)
而不是
AND emp.pay_type = 'FT'
我对这里发生的事情感到困惑,因此,我也很困惑为什么这会提高性能。由于FT是SQL查询中的字符串文字,因此永远不会为NULL,为什么这会有什么不同呢?我猜这与现场的现有索引有关,但我无法在Oracle文档中找到任何内容。
答案 0 :(得分:4)
这是一个奇怪的建议。 NVL功能如下:
NVL(exp1, val1)
如果'exp1'不为null,则返回;否则返回'val1'。
由于示例中的“FT”不能为NULL,因此使用NVL函数没有任何好处,并且性能损失很小(至少对于优化器来说,NVL是多余的;如果优化器可能会执行处罚没有证明NVL是多余的。)
如果条件为:
AND emp.pay_type = NVL(“FT”,UID)
那么可能会有一个好处;这里我们有一个分隔标识符(用双引号括起来的列名),列值可能是NULL; NVL调用确保仅当“FT”为NULL 并且 UID为NULL时才返回NULL。当然,UID是常规标识符。如果条件为:
,则可能有意义AND emp.pay_type = NVL(UID, 'FT')
现在,如果UID值为NULL,则使用默认值“FT”作为相应的pay_type。
答案 1 :(得分:3)
我会用大量的盐来蟾蜍的“优化建议”。我把它们称为“霰弹枪”优化方法 - 在目标上射出很多不同的位,看看它们中的哪一个命中,不知何故:)
无论如何,
之间的区别AND emp.pay_type = NVL('FT', UID)
和
AND emp.pay_type = 'FT'
在第二种情况下,优化器可以使用列上的直方图统计信息(如果它们已被收集)以获得更准确的匹配行数估计。但是,当使用NVL时,优化器(我相信)不会检测到它可以忽略NVL,因此不会检查直方图的值。
这不是我通常使用的优化方法。有更好的方法来控制查询的执行路径(例如提示)。特别是,如果这些方法改进了CBO以寻找和优化冗余代码,例如NVL([literal value],[anything])
到[literal value]
,那么这种方法就会失败。
答案 2 :(得分:1)
Oracle的解释计划告诉您有关这两个查询的内容是什么?