考虑以下情况。我有一个表格(一个stupid_table
)在我无法控制的架构中。这是第三方,不受限制。没有敏感。我可以查询它,但不添加索引或新表或更改设计。如何防止Oracle的基于成本的优化器进行糟糕的优化?
stupid_table
中的每一列都是VARCHAR2(50 BYTE)
,有很多列,但我只需要其中的两列:row_type
和magic_number
。 magic_number
填充了整数的字符串表示形式,但只有其中row_type
设置为'DATA'
,我只需要大于零的幻数。
SELECT TO_NUMBER(magic_number)
FROM stupid_table
WHERE row_type = 'DATA'
AND TO_NUMBER(magic_number) > 0;
这将导致一个“无效号码” Oracle错误,因为基于成本的优化器(CBO)是选择检查row_type
之前评估TO_NUMBER
并有行一大堆用不同row_type
和magic_number
字段的不同用途。
好吧,如果我先过滤行,然后再进行比较呢?
SELECT TO_NUMBER(t.magic_number)
FROM (
SELECT magic_number
FROM stupid_table
WHERE row_type = 'DATA'
) t
AND TO_NUMBER(t.magic_number) > 0;
现在CBO似乎摸出查询是很简单,忽略了我已经使用,产生相同的查询计划到原来的狡猾。
最后,我沮丧地采取了肮脏的黑客行为:使用/*+RULE*/
查询提示强制Oracle使用旧的基于规则的优化器。这就像一场梦,但它不应该是必须的,更不用说它正在使用不再支持的Oracle特性。
有没有更好的方法来做到这一点?
有时最简单的解决方案往往是最好的。虽然这可能不是解决这类问题的最佳通用解决方案,但它能以最高性能的方式解决*我的特殊问题。 – ninesided 2010-11-12 10:46:29