2016-12-12 13 views
4

データベースで長いこと遠く離れた開発者が、述語の書かれた順序に依存している問合せを作成しました。例えばOracle 12cインライン・ビュー評価

select x 
    from a, b 
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
    and a.char_column = b.numeric_column; 

(計画は to_number変換は a.char_columnに適用されます示唆して説明)

私はこの "だけの作品"(Oracle 11gの)を設計よりも多くの偶然だと思います。ただし、Oracle 12cで実行しているときには述語の順序が守られていないため、この問合せは無効な例外で破損します。私は

select /*+ ORDERED_PREDICATES +*/ x 
    from a, b 
where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
    and a.char_column = b.numeric_column 

を次のように私はORDERED_PREDICATESヒントを使用して順番に述語を評価するために12Cを強制的に試みることができることを承知している。..や比較のためto_charを使用して値のいずれかをキャスト。欠点は、to_charが100万行で動作できることです。私は次のインラインビューはおそらくより良い解決策だと思う。インラインビューが最初に評価されることを保証していますか?

select x 
    from b 
    inner join (
       select only_rows_with_numeric_values as numeric_column 
       from a 
       where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
      ) c 
    on c.numeric_column = b.numeric_column; 
+0

あなたはbテーブルに何百万もの行があると言っています( '欠点はto_char could op例えば100万行になると言う。暗黙的な変換が行われるため、to_number関数が適用されるため、表の中にいくつの行がありますか?テーブルに同じ(またはそれ以上の)行がある場合、to_charのためにパフォーマンスに悪影響を与えることはありません。 – Boneist

+1

また、数値aのみを含むテーブルaに仮想列を作成し、その列にインデックスを付けることができます。クエリは、 'a.new_numeric_virtual_column = b.numeric_column;の内部結合bからxを選択するように単純化できます。 ' – Boneist

+0

さて、それはアイデアです!私は仮想列を考慮しなかったことを認めなければならない!提案していただきありがとうございます! – 0909EM

答えて

1

述語の順序について - https://jonathanlewis.wordpress.com/2015/06/02/predicate-order-2/

を見てあなたは、クエリネストを解除または単にヒントを使用を抑制するためにドキュメントによるとrownumhttps://docs.oracle.com/database/121/SQLRF/queries008.htm#SQLRF52358

select x 
    from b 
    inner join (
       select only_rows_with_numeric_values as numeric_column, 
       rownum 
       from a 
       where NOT REGEXP_LIKE (a.column, '[^[:digit:]]') 
      ) c 
    on c.numeric_column = b.numeric_column; 

を使用して、次へのあなたの最後のクエリを書き直す必要があります/*+ no_unnest*/

+0

Jonathan Lewisへのリンクありがとう!私のグーグルでは、私はrownumを参照してくださいが、Oracleのドキュメントでは、リンクのおかげでそれを見ることができませんでした。 – 0909EM