3

11/2更新

追加のトラブルシューティングを行った後、私のチームは、この Oracle のバグを12c、クエリが機能しなくなる前夜にデータベースで行われたパラメーターの変更に直接関連付けることができました。このデータベースに関連付けられたアプリケーションでパフォーマンスの問題が発生した後、私のチームは DBA にOPTIMIZER_FEATURES_ENABLEパラメータを から12.1.02に変更してもらいました11.2.0.4。これにより、問題のアプリケーションのパフォーマンスの問題は修正されましたが、上記のバグが発生しました。確認のために、このパラメーターを変更することで、別の環境で同じ問題を再現できました。私の DBA は、これを確認するために Oracle にチケットを提出しました。

回避策として、期待される結果を取得するためにクエリを少し変更することができました。具体的には、Subquery1withを組み合わせてSubquery2、いくつかの述語を句から the Subquery1(より適切に属する場所) に移動しました。この変更により、実行計画が編集されました (以前にリストされたものよりも効率がわずかに低下します) が、元の問題に対処するには十分でした。WHEREJOIN


元の投稿

まず、この質問が曖昧であることをお詫びしますが、機密の金融システムを扱っているため、特定の実装の詳細を非表示にする必要があります。

バックグラウンド

Oracleかなり前に本番環境に投入したクエリがありますが、最近、 から11gへのアップグレード後に予期した結果が偶然に生成されなくなりました12c。私 (および私のプロダクション サポート チーム) の知る限り、このクエリはその 1 年以上前から問題なく機能していました。

詳細

クエリは非常に複雑であまり効率的ではありませんが、これは主に、正規化されていないテーブル (歴史的にメインフレームをモデルにしたもの) と上流システムからの不十分なデータ入力を扱っているためです。複雑なビジネス状況に対処するために、複数レベルのサブクエリ ファクタリング (WITHステートメント) を活用し、最終的なステートメントで 2 つのインライン ビューを結合しました。複雑な述語をすべて除いたクエリの基本構造は次のとおりです。

私は3つのテーブルを持っていますTable1, Table2, Table3. Table1からのレコードで構成される処理テーブルTable2です。

--This grabs a subset from Table1
WITH Subquery1 as (
   SELECT FROM Table1),

--This eliminates certain records from the first subset based on sister records 
--from the original source table 
Subquery2 as (
   SELECT FROM Subquery1
   WHERE NOT EXISTS FROM (SELECT from Table2)),

--This ties the records from Subquery2 to Table3
Subquery3 as (
   SELECT FROM Table3
   JOIN (SELECT Max(Date) FROM Table3)
   JOIN Subquery2)

--This final query evaluates subquery3 in two different ways and 
--only takes those records which fit the criteria items from both sets
SELECT FROM 
(SELECT FROM Subquery3)             -- Call this Inline View A
JOIN (SELECT FROM Subquery3)        -- Call this Inline View B

最後のクエリは非常に基本的なものです。

   SELECT A.Group_No, B.Sub_Group, B.Key, B.Lob               
   FROM   (SELECT Group_No, Lob, COUNT(Sub_Group) 
           FROM   Subquery3 
           GROUP BY Group_No, Lob
           HAVING COUNT(Sub_Group) = 1) A 
   JOIN (SELECT Group_No, Sub_Group, Key, Lob
         FROM   Subquery3 
         WHERE  Sub_Group LIKE '0000%') B 
   ON A.Group_No = B.Group_No
   AND A.Lob = B.Lob

問題

最後のクエリを編集して 2 番目のインライン ビューを削除し、インライン ビューの出力を評価すると、返された行A0 になります。個々のサブクエリのレコードを手動で評価したところ、これが予期された結果であることを確認できました。

同様に、最後のクエリを編集して「B」インライン ビューのみの出力を生成すると、6 つの行が返されます。繰り返しますが、手動でデータを評価しましたが、これはまさに期待どおりです。

これら 2 つのサブセット (Inline ViewAと Inline View B) を結合すると、最終的なクエリ結果は 0 行になると予想されます (完全なセットと空のセットの間の内部結合では一致が生成されないため)。ただし、上記のように内部結合を使用してクエリ全体を実行すると、1158 行が返されます。

実行計画を確認しましたが、何も思い浮かびません:

実行計画 1 実行計画 2

質問

明らかに、私は Oracle Optimizer を混乱させるために何かを行っており、更新されたクエリ プランは、送信したものとはかなり異なるクエリを引き戻しています。私の最善の推測では、これらの一時的なビューがすべて同じクエリ内に浮かんでいるため、Oracle を混乱させて、依存するセットの前にいくつかのセットを評価してしまったのです。

今日に至るまで、このWITHステートメントに関する公式の Oracle ドキュメントを見つけることができなかったので、サブクエリが評価される順序について完全に確信を持ったことはありませんでした。SO の検索で気付きました (今は見つかりません) 誰かが、因数分解されたサブクエリは別の因数分解されたクエリを参照できないと述べました。これが本当だとは今まで知らなかったのですが、上記の奇妙な出力を見ると、このクエリで運が良かったのではないかと思います。

誰かが私が見ている動作を説明できますか? このクエリ プランで明らかに間違ったことをしようとしていますか? または、11g と 12c の間で何かが変更され、このクエリの動作が変更された理由を説明できる可能性はありますか?

4

1 に答える 1

2

これは、Oracle の「間違った結果」バグのように思えます。これらのバグは通常、使用しているバージョンと機能に非常に固有のものです。投稿したクエリまたは実行計画に明らかな問題はありません。

これを処理するには、次の 2 つの方法があります。

  1. 正確なバグを見つけてみてください。 共通テーブル式で行っていることは問題ないようです。まれに、クエリが技術的に無効である場合があります。あるバージョンで「幸運」になり、それが機能し、アップグレードすると失敗します。しかし、それが発生した場合、通常、新しいバージョンはエラーをスローし、間違った結果を返しません。おそらく、使用している機能の非常に奇妙で特定の組み合わせが問題を引き起こしている可能性があります。本当の問題を見つけるには、可能な限り小さな変更を加えて問題が現れたり消えたりするまで、クエリを大幅に単純化する必要があります。また、すべてのオブジェクトを削除して、 のみを使用することもできますDUAL。このプロセスには数時間かかる場合があります。最後に、数行のコードしか残っていない場合は、ここに投稿するか、Oracle サポートを調べてください。
  2. バグを回避します。 上記の手順を実行しても、いずれにしても修正されない場合があります。最善の回避策は、別のことを行うことである場合があります。すべての問題の根底に到達するのは素晴らしいことですが、常に時間があるとは限りません。代わりに、構文的には異なるが論理的には同等の方法でクエリを書き直してみてください。共通のテーブル式の一部またはすべてを削除し、場合によっては一部の SQL を繰り返します。ただし、将来のプログラマーに対して、なぜ奇妙な方法で物事を行っているのかを警告するコメントを必ず残してください。
于 2016-10-29T17:08:33.800 に答える