2016-09-02 6 views
4

プロダクションには独自の問題があります。真夜中に私たちのOracle 12cデータベースはバッチ・サイクル中にハングするでしょう。我々は数日/数週間続けていくためにデータベースを再起動する必要があります。その後、再び起こります。私はテーブルの名前を変更しましたOracle UPDATEの不思議なデカルト製品

UPDATE c_bill SET reason_desc = (SELECT description FROM codes 
WHERE code_group = 'TRANSACTION_TYPE' AND code = c_bill.reason_code); 

- しかし、コード表はコードと説明があります。 いくつかの掘削後、私たちは、このSQLにそれを絞られています。開発者はこの記述をc_billテーブルにコピーしようとしています。

このSQLは、バッチジョブの一部として夜間に実行されるストアドプロシージャの一部です。開発者はこれの直前に別の更新を行いますが、これは問題ありませんが、このSQLには長い時間がかかります。

特定の実行中、テーブルには36308行ありました。 = 36308 *

Rows_processedを上記のアップデート1318270864のための第一の更新36308 Rows_processedのために、それがあることをhapppens:私は生産DB(私は五$ SQLテーブル内のSQL文を見て)を確認すると、私は以下を参照してください。 36308 !! (デカルト積?)

TESTではこの問題はありません。私がUPDATEを試して、それをTESTで説明しましたが、UPDATEとv $ sqlの両方に正確に36308個の行が表示されます。

これは困惑しています。誰かがそのSQLのデカルト積のチャンスを見ますか?あるいは、Oracle 12cオプティマイザのデカルトをデカルト製品に変える可能性のあるバグを知っていますか?(グループでバグを修正するためにいくつかのパッチを適用しました)

私はOracleにかなりの経験があります。ここではクエリを調整しています。私は開発者にどこに条件を付け加えてほしいかを提案しました。私たちはまだそれをテストしています。その間、オラクルの専門家が合格するために渡したかったのです。すべてのコメント/提案は非常に感謝しています。

UPDATE:将来的には、この記事を見ている人のため - 問題が直積ではなく、目の同じテーブルの上にカーソルをループ内で実行されている問題の更新SQL、したがって、デカルトのように見えます。ジャスティンの答えを見てください。

+1

'' v $ sql' 1に 'executions'がありますか?それとも36308ですか(つまり、36308回の実行ごとに36308行更新されました)?あなたは実際にデカルト積があるかどうかを調べるために、(共有プールまたはAWR/Statspackからの)ステートメントのクエリプランを入手できますか?'c_bill'は' code_group'や 'code'という名前の列を持っていますか?それとも' codes'にしか存在しませんか? –

+0

私はあなたがそれを釘付けにしたかもしれないと思います! Executions = 36308、そしてそれがあるプロシージャは、c_billテーブルのキーの行をピックアップするカーソルを持っています。私が言及した前回の更新では、実際にカーソルのSQLで使われていたキーがありましたが、これはそうしませんでした。私はいくつかのテストを行い、ポストバックします。私はDBAではない、私はAWRの統計を来週チェックする(彼らは長いw/eのために今行っている!)。回答として返信していただけますか? – SamV

+0

v $ sqlから、問題のUPDATEステートメントのlast_load_timeがlast_load_timeが2016-09-02/03:04:02 、last_active_timeが09/02/2016 4:48であった。これは、同じSQLがその時間に36308回実行されたことを意味しますか? – SamV

答えて

1

私の最初の考えは、あなたがデカルト製品をやっているという悪い計画を持っているという理論を確認したり反駁したりする証拠を収集しようとすることでしょう。 はv$sqlにありますか?または36308? 1であれば、デカルト積理論をサポートします。この問題が発生したかどうか、AWRの使用許諾を受けているかどうかに応じて、v$sql_planまたはdba_hist_sql_planでクエリプランを探し始めます。一方、36308の場合は、クエリが36308行を更新していることを意味しますが、何かがテーブルのすべての行をループしようとしているため、36308回呼び出されました。

+0

偉大な答え!謎を突き止めるのを助けました。 DBAが今朝Gridコントロールからトップアクティビティチャートを送信したとき、1つのSQLがそれを長く取っていたように見えました。あなたが言ったように、実際には、キャッシュされたSQLを1時間以上何度も実行し続けていました。今朝の問題を見てみると、外側のループが同じテーブルを使用していなかったことに気が付きました。私のためにそれを絞り込むためにありがとう! – SamV

1

ここで説明している動作の理由がわかりません。とにかく、回避策として、あなたはこのような、別のUPDATEと試みることができる:私は実際に今のOracleでこの声明をしようとするため

UPDATE 
    (SELECT c_bill.reason_desc oldDesc, codes.description newDesc 
    FROM c_bill INNER JOIN codes ON 
     code.code_group = 'TRANSACTION_TYPE' AND 
     codes.code = c_bill.reason_code) 
SET oldDesc = newDesc 

残念ながら、それは難しいです。私はこれまでにこの種のアップデートを見たことがあることを知っています。

+0

あなたの提案に感謝@ゾラン。私はそれを試しました、それは間違いなくそれが欠けていた条件を追加します。しかし、SQLは以前のバージョンよりはるかに優れていませんでした。 Justin Caveのコメントに基づいて、私は処刑を見て、それは36308回実行していました!だから、私はSQLがループ内にあり、条件によってデカルト積に似ているとは思えません。私はテストした後、私の所見を返信します。 – SamV

+1

あなたの質問は非常に有益でした、私たちはすべてそれから何かを学んだと思います。 –