【发布时间】:2011-05-08 14:52:48
【问题描述】:
考虑以下场景。我在我无法控制的架构中有一个表(stupid_table)。它是第三方,不受限制。没有敏感。我可以查询它,但不能添加索引或新表或更改设计。
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 功能。
有没有更好的方法来做到这一点?
【问题讨论】: