次のシナリオを検討してください。stupid_table
制御できないスキーマにテーブル (a ) があります。立ち入り禁止の第三者です。触らない。クエリはできますが、インデックスや新しいテーブルを追加したり、デザインを変更したりすることはできません。
のすべての列はstupid_table
です。多くの列がありますが、必要なのはとVARCHAR2(50 BYTE)
の 2 つだけです。には整数の文字列表現が取り込まれますが、が に設定されている場合のみ、0 より大きいマジック ナンバーのみが必要です。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 エラーが発生します。これは、Cost Based Optimiser (CBO) が をTO_NUMBER
チェックする前にを評価することを選択しており、フィールドの使用方法が異なる多数row_type
の行があるためです。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 の機能を使用していることは言うまでもなく、必要ではありません。
これを行うより良い方法はありますか?