5

突然(残念ながら、「突然」がいつだったのかはわかりません。過去のある時点で正常に実行されたことはわかっています)、クエリの1つが実行にミリ秒ではなく7秒以上かかり始めました。DB リンクを介して 1 つのローカル テーブルと 3 つのテーブルにアクセスしています。3 つのリモート テーブルが結合され、そのうちの 1 つがローカル テーブルと結合されます。

ローカル テーブルの where 句は、単独で実行するのに数ミリしかかからず、少数 (多くても 10 または 100) のレコードしか返しません。3 つのリモート テーブルの間には数十万、場合によっては数百万のレコードがあり、それらを適切に結合すると、数万または数十万のレコードが得られます。

ローカル テーブルの各レコードに関連するいくつかのデータを取得できるように、リモート テーブルとのみ結合しています。

しかし、何が起こっているように見えるかというと、Oracle は最初にリモート テーブルを結合し、次にローカル テーブルを最後にその混乱に結合します。特に現在存在するデータセットを考えると、これは常に悪い考えになるため/*+ LEADING(local_tab remote_tab_1) */、クエリにヒントを追加したところ、ミリ秒単位で返されるようになりました。

BUFFER SORT説明計画を比較したところ、リモート テーブルの 1 つを除いてほぼ同じです。

オラクルがこれに間違った方法でアプローチする原因は何でしょうか? 指数の問題ですか?何を探すべきですか?

4

5 に答える 5

5

実行計画を選択するとき、オラクルはさまざまな計画のコストを見積もります。その見積もりの​​重要な情報の1つは、実行プランのステップから返される行の量です。Oracleは、「統計」を使用してそれらを推定しようとします。つまり、テーブルに含まれる行数、列に含まれるさまざまな値の数に関する情報です。これらの値がどの程度均等に分散されているか。

これらの統計はまさにその統計であり、間違っている可能性があります。これは、オラクルオプティマイザの誤判断の最も重要な理由の1つです。

したがって、コメントで説明されているように新しい統計を収集すると役立つ場合があります。そのdbms_statsパッケージのドキュメントをご覧ください。そのパッケージを呼び出すには、さまざまな方法があります。

于 2010-02-23T21:28:21.303 に答える
3

私が遭遇した一般的な問題は、多くのテーブルを結合するクエリです。結合は一方の端から他方の端までチェーンを形成します。

SELECT *
FROM   tableA, tableB, tableC, tableD, tableE
WHERE  tableA.ID0 = :bind1
AND    tableA.ID1 = tableB.ID1
AND    tableB.ID2 = tableC.ID2
AND    tableC.ID3 = tableD.ID3
AND    tableD.ID4 = tableE.ID4
AND    tableE.ID5 = :bind2;

オプティマイザーが tableA (たとえば、ID0 のインデックスが適切に選択的である場合) または tableE (tableE.ID5 のインデックスがより選択的である場合) からクエリを実行する方法を選択することに注意してください。

テーブルの統計により、これら 2 つの計画のどちらを選択するかがナイフエッジでバランスを取る可能性があります。ある日は正常に動作し (テーブル A から駆動)、翌日には新しい統計が収集され、突然、テーブル E から駆動する代替プランのコストが低くなり、選択されます。

この状況では、LEADING ヒントを追加することは、オプティマイザーにあまり多くを指示することなく (つまり、オプティマイザーに特定の結合方法の選択を強制することなく) 元の計画 (つまり、tableA からのドライブ) に戻す1 つの方法です。

于 2010-02-24T07:46:35.300 に答える
2

あなたは分散クエリの最適化を行っていますが、それはトリッキーな獣です。テーブルの統計は最新のものである可能性がありますが、リモート システムのテーブルは不安定であるか、変更されています。または、リモート システムがインデックスを追加/削除/変更したため、計画が破られました。(これは、レプリケーションを検討する優れた理由です。したがって、レプリケーションに対するインデックスと統計を制御できます。)

とはいえ、オラクルのカーディナリティの見積もりは、実行計画の主要な要因です。10053 トレース分析 (Jonathan Lewis の Cost-Based Oracle Fundamentals の本には、8i から 10.1 までの素晴らしい例が掲載されています) は、ステートメントが壊れている理由と、LEADINGヒントがそれを修正する方法を明らかにするのに役立ちます。

DRIVING_SITEリモート サイトに移動する前にローカル テーブルを最初に結合することが常に必要であることがわかっている場合は、ヒントを選択することをお勧めします。LEADINGヒントのように計画を進めることなく、意図を明確にします。

于 2010-02-24T15:26:50.600 に答える
1

り、

SQL を確認せずに、パフォーマンスの問題の原因を特定することは困難です。

Oracle クエリのパフォーマンスが以前は良好で、突然パフォーマンスが低下し始めた場合、通常は次の 2 つの問題のいずれかに関連しています。

A) 統計が古くなっています。これは、チェックするのが最も簡単で迅速なことです。それを処理するはずのハウスキーピング バッチ プロセスがある場合でも、常に再確認してください。

B) データ量/データパターンの変更。

あなたの場合、複数のデータベース間で分散クエリを実行すると、Oracle がデータベース間のパフォーマンスを管理することが 10 倍難しくなります。これらのテーブルを 1 つのデータベースに配置することは可能ですか? おそらく、1 つのデータベースに別のスキーマ所有者を配置することはできますか?

オラクルはヒントに従う義務を負っていないため、ヒントは壊れやすいことで有名です。データの量やパターンがさらに変化すると、Oracle はヒントを無視して、最適と判断した処理 (つまり、最悪の処理) を実行する可能性があります。

これらのテーブルをすべて 1 つのデータベースに配置できない場合は、クエリを 2 つのステートメントに分割することをお勧めします。

  1. サブ SELECT で INSERT を実行して、外部データを現在のデータベースのグローバル一時テーブルにコピーします。
  2. グローバル一時テーブルから SELECT して、他のテーブルと結合します。

ヒントに頼ることなく、上記のステップ 1 のパフォーマンスを完全に制御できます。このアプローチは通常、パフォーマンスの調整に時間がかかる場合は、適切にスケーリングされます。このアプローチが多くの複雑なパフォーマンスの問題を解決するのを見てきました。

Oracle がまったく新しいテーブルを作成したり、レコードのヒープを挿入したりするためのオーバーヘッドは、ほとんどの人が予想するよりもはるかに小さいです。グローバル一時テーブルを定義すると、そのオーバーヘッドがさらに削減されます。

マシュー

于 2010-02-25T14:45:58.367 に答える
1

関係ないかもしれませんが、リモートテーブルが単一テーブルビューに置き換えられたときに、同様の状況が発生しました。それがテーブルの場合、分散クエリ オプティマイザーは、インデックスがあることを「認識」しました。ビューになると、インデックスが表示されなくなり、リモート オブジェクトでインデックスを使用するプランを実行できなくなりました。

それは数年前のことです。当時の私の分析をここに記録しました。

于 2010-02-24T22:17:07.430 に答える