Oracle の主要なヒント — なぜこれが必要なのでしょうか?
-
22-09-2019 - |
質問
突然(しかし残念なことに、「突然」がいつなのかはわかりません。過去のある時点で正常に実行されたことはわかっています) クエリの 1 つが実行にミリ秒ではなく 7 秒以上かかるようになりました。1 つのローカルテーブルと 3 つのテーブルが DB リンク経由でアクセスされています。3 つのリモート テーブルが結合され、そのうちの 1 つがローカル テーブルと結合されます。
ローカル テーブルの where 句は、単独で実行するのに数ミリしかかからず、数件 (最大でも 10 件、または 100 件) のレコードのみを返します。3 つのリモート テーブル間には数十万、場合によっては数百万のレコードがあり、それらを適切に結合すると、数万または数十万のレコードが得られます。
ローカル テーブルの各レコードに関連するデータをいくつか取り出すために、リモート テーブルに結合しているだけです。
ただし、起こっているように見えるのは、Oracle が最初にリモート テーブルを結合し、最後にローカル テーブルをその混乱に結合することです。特に現在存在するデータセットを考えると、これは常に悪い考えであるため、 /*+ LEADING(local_tab remote_tab_1) */
私のクエリにヒントを与えると、ミリ秒単位で返されるようになりました。
説明プランを比較しましたが、1 つの点を除いてほぼ同じです。 BUFFER SORT
リモートテーブルの 1 つで。
Oracle がこれに対して間違ったアプローチをする原因は何でしょうか?インデックスの問題でしょうか?何を探せばいいのでしょうか?
解決
は、Oracleは異なるプランのコストを推定します。その推定のための一つの重要な情報は、行の量は、実行計画の段階から返されますです。 Oracleは、「統計」、すなわちに関する情報を使用して、これらを推定しようとすると、テーブルに含まれる行数を、どのように多くの異なる値の列が含まれています。どのように均等にこれらの値が配布されます。
これらの統計は統計は、彼らはOracleオプティマイザの誤判定のための最も重要な理由の一つである、間違っているかもしれないだけのことです。
コメントのかもしれないのヘルプで説明したように、だから、新しい統計を収集。そのDBMS_STATSパッケージのドキュメントを見てください。そのパッケージを呼び出すにはさまざまな方法があります。
他のヒント
私は全体来て一般的な問題はどこ例えば、一方の端から別のチェーンを形成加わり、多くのテーブルを結合するクエリです
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;
お知らせ方法オプティマイザは、(tableE.ID5上のインデックスは、より選択的である場合)またはtableEから(ID0上のインデックスがうまく選択され、例えば場合)にtableAからクエリを駆動することを選択するかもしれません。
表の統計は、ナイフエッジのバランスにこれらの2つのプランの間の選択を引き起こす可能性があります。それは罰金(にtableAから駆動)、次の日に働いて1日が新しい統計情報が収集され、すべてが突然tableEから駆動の代替案は、低コストを持っており、選択されます。
この状況では、LEADINGヒントを追加する(すなわち、それは強制するものではありません一つの方法のはのオプティマイザにあまりにも多くの口述せずに元の計画(にtableAからすなわちドライブ)にそれを微調整することです任意の特定の結合方法を選択するオプティマイザ)。
あなたは、分散クエリの最適化をやっている、それはトリッキーな獣です。それはあなたのテーブルの統計情報が最新のものであるが、今、リモート・システムでのテーブルはアウト・オブ・強打されているか、変更されていることが考えられます。またはリモートシステムを追加/削除/変更インデックス、あなたの計画を壊しました。 (これは、レプリケーションを検討するための優れた理由である - 。あなたはそれに対して、インデックスと統計を制御することができるように)
言っは、カーディナリティのOracleの推定値は、実行計画の主な要因です。 10053微量分析は(ジョナサン・ルイスのコストベースのOracleの基礎本が8Iから10.1への素晴らしい例があります)缶の助けはあなたの声明のが今壊れ、どのようLEADING
ヒント修正それ理由に光当てます。
DRIVING_SITE
ヒントは、あなたが常にローカルのテーブルは、リモートサイトの後に行く前に最初に参加することにしたい知っていればより良い選択かもしれません。それが道に計画を駆動せずLEADING
ヒントをあなたの意図を明確になります。
は関係ない場合もありますが、私は、リモート表が単一のテーブルビューに置き換えられていたところ、一度似たような状況がありました。インデックスを持っていたこと、テーブル、分散クエリオプティマイザ「のこぎり」だったとき。それはビューになったとき、それはもう、インデックスを見ることができなかったし、リモートオブジェクト上のインデックスを使用する計画はかかりませんでした。
数年前だった。私は<ここに時間で私の分析を文書化/ A>。
り、
SQL を見ないと、パフォーマンスの問題の原因を確信するのは困難です。
Oracle クエリのパフォーマンスが以前は良好であったのに、突然パフォーマンスが悪くなり始めた場合、通常は次の 2 つの問題のいずれかに関連しています。
A) 統計は古いです。これは、それを処理するはずのハウスキーピング バッチ プロセスがある場合でも、最も簡単かつ迅速にチェックできることです。常にダブルチェックしてください。
B) データ量/データパターンの変更。
あなたの場合、複数のデータベースにわたって分散クエリを実行すると、Oracle がデータベース間のパフォーマンスを管理することが 10 倍難しくなります。これらのテーブルを 1 つのデータベースに配置することは可能でしょうか。おそらく、1 つのデータベースに別々のスキーマ所有者を配置することは可能でしょうか?
オラクルにはヒントに従う義務がないため、ヒントは脆弱であることで有名です。データの量やパターンがさらに変化すると、Oracle はヒントを無視して、最善と思われることを実行する可能性があります (つまり、最悪 ;-)。
これらのテーブルをすべて 1 つのデータベースに入れることができない場合は、クエリを 2 つのステートメントに分割することをお勧めします。
- サブ SELECT で INSERT を実行すると、外部データが現在のデータベースのグローバル一時テーブルにコピーされます。
- グローバル一時テーブルから SELECT を実行して、他のテーブルと結合します。
ヒントに頼ることなく、上記のステップ 1 のパフォーマンスを完全に制御できます。通常、このアプローチは、時間をかけてパフォーマンスのチューニングを行う限り、適切に拡張できます。このアプローチが多くの複雑なパフォーマンス問題を解決するのを私は見てきました。
Oracle がまったく新しいテーブルを作成したり、レコードのヒープを挿入したりする際のオーバーヘッドは、ほとんどの人が予想するよりもはるかに小さいです。グローバル一時テーブルを定義すると、このオーバーヘッドがさらに削減されます。
マシュー