作業中のOracleインスタンスから奇妙な動作が発生します。これはItanium上の11gR1であり、RACはなく、特別なものはありません。最終的には、データウェアハウスのシナリオで、あるOracleインスタンスから別のインスタンスにデータを移動します。
DBリンク上で実行されている半複雑なビューがあります。大規模なテーブルに対する4つの内部結合と、中規模のテーブルに対する5つの左側の結合。
問題は次のとおりです。SQLDeveloper(またはSQL * Plus)でビューをテストすると、問題はなく、重複はまったくありません。ただし、実際にビューを使用してデータをテーブルに挿入すると、多数の重複が発生します。
編集:-データは空のテーブルに入ります。クエリ内のすべてのテーブルはデータベースリンク上にあります。クエリに渡されるのは日付だけです(たとえば、INSERT INTO target SELECT * FROM view WHERE view.datecol = dQueryDate)-
ビューのPKでパーティション化されたROW_NUMBER()関数をselectステートメントに追加してみました。すべての行は1として番号が付けられて戻ってきます。ただし、挿入として実行された同じステートメントは、以前と同じ重複を生成し、現在は便利な番号が付けられています。重複した行の数は、キーごとに同じではありません。一部のレコードは4回存在し、一部は1回だけ存在します。
私はこれが行動に非常に当惑していると思います。:) SETテーブル(一意の行のみ)とMULTISETテーブル(重複行が許可されている)があるTeradataでの作業を思い出させますが、Oracleにはそのような機能はありません。
行をクライアントに返すselectは、それらの行を別の場所に挿入するselectと同じように動作する必要があります。これが起こる正当な理由を想像することはできませんが、おそらく私は想像力の失敗に苦しんでいます。;)
他の誰かがこれを経験したのか、それともこのプラットフォームのバグなのかしら。
解決
@Garyのおかげで、「EXPLAIN PLAN FOR {my query};」を使用して、この問題を解決することができました。および「SELECT*FROM TABLE(dbms_xplan.display);」。実際にINSERTに使用される説明は、SELECTとは大きく異なります。
SELECTの場合、ほとんどのプラン操作は「INDEXROWIDによるTABLEACCESS」および「INDEXUNIQUESCAN」です。'Predicate Information'ブロックには、クエリからのすべての結合とフィルターが含まれています。最後に「注-完全にリモートステートメント」と表示されます。
INSERTの場合、インデックスへの参照はありません。「述語情報」ブロックはわずか3行で、新しい「リモートSQL」ブロックには9つの小さなSQLステートメントが表示されます。
データベースは私のクエリを9つのサブクエリに分割し、それらをローカルで結合しようとします。小さい方の選択を実行することで、重複のソースを見つけました。
これは、リモートリンクに関するOracleコンパイラのバグだと思います。SQLを書き直すときに論理的な欠陥が発生します。基本的に、コンパイラはWHERE句を適切に適用していません。私はちょうどそれをテストしていて、持ち帰るための5つのキーのINリストを与えました。SELECTは5行を戻します。INSERTは、77,000以上の行をターゲットに配置し、INリストを完全に無視します。
{正しい動作を強制する方法をまだ探していますが、開発の観点からは理想的ではありませんが、リモートデータベースにビューを作成するように依頼する必要があるかもしれません。動作するようになったら編集します…}