0

t_reading次のスキーマを持つ というテーブルがあります。

MEAS_ASS_ID     NUMBER(12,0)
READ_DATE       DATE
READ_TIME       VARCHAR2(5 BYTE)
NUMERIC_VAL     NUMBER
CHANGE_REASON   VARCHAR2(240 BYTE)
OLD_IND         NUMBER(1,0)

この表は、次のように索引付けされています。

CREATE INDEX RED_X4 ON T_READING
(
  "OLD_IND",
  "READ_DATE" DESC,
  "MEAS_ASS_ID",
  "READ_TIME"
)

この正確なテーブル (同じデータを持つ) は 2 つのサーバーに存在します。唯一の違いは、それぞれにインストールされている Oracle のバージョンです。

問題のクエリは次のとおりです。

SELECT * FROM t_reading WHERE OLD_IND = 0 AND MEAS_ASS_ID IN (5022, 5003) AND read_date BETWEEN to_date('30/10/2012', 'dd/mm/yyyy') AND to_date('31/10/2012', 'dd/mm/yyyy');

このクエリは、Oracle 10 では 1 秒未満で実行され、Oracle 9 では約 1 分で実行されます。

何か不足していますか?

編集:

Oracle 9 の実行計画: ここに画像の説明を入力

Oracle 10 の実行計画: ここに画像の説明を入力

4

4 に答える 4

1

いくつかの潜在的な説明:

  • さまざまなインデックスを範囲スキャンしています。
  • 10g テーブルに同じインデックスがあり、それを別のものと呼んでいると仮定すると、Explain Plan は異なります。

主な懸念は、9i クエリの実行計画の行、バイト、およびコストの列に情報が不足していることです。Oracle 9i はデフォルトでは統計を収集しませ。この詳細は、このテーブルの統計を収集していないことを示しています。dbms_statsテーブルとインデックスの統計を収集するために使用します。具体的な手順gather_table_stats

BEGIN

    DBMS_STATS.GATHER_TABLE_STATS (
       ownname => user, 
       tabname => 'T_READING', 
       estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE
       method_opt => 'FOR ALL INDEXED COLUMNS',
       cascade => TRUE, -- gather index statistics
        );
END:

興味があれば、他にもたくさんのオプションがあります。インデックスが異なると仮定すると、これCBO (「オン」になっていると仮定) が正しいインデックスを選択するのに役立ちます。

他のオプションには、それらがどのサーバー上にあるか、およびデータベースパラメーターが何であるかが含まれます。それらが異なるサーバー上にある場合、相対的な「パワー」、ディスク速度、I/O、および他のオプションの終わりのないリストによって、簡単に違いが生じる可能性があります. データベース パラメータが異なる場合、同じ問題が発生します。

データベースのチューニングは科学であると同時に芸術でもあります。オラクルにはそれに関する本があり、他にもたくさんのリソースがあります。

于 2012-10-31T08:46:23.323 に答える
1

「何か足りない?」

ほぼ確実ですが、何をお伝えするかは難しいです。

9i から 10g への CBO ではいくつかのパフォーマンスの改善がありましたが、それほど大きな違いはないと思われます。したがって、それはあなたのシステムの何らかの変動であるに違いありません。これは明らかに、私たちが盲目で遠隔地にいるため、診断するのが最も難しいことです.

したがって、最初に除外すべきことは、一般的なシステムの違い (ディスク速度、I/O ボトルネック、メモリ サイズなど) です。サーバーが 2 つあるとおっしゃいましたが、それらの仕様は異なりますか? これらのことを調査するには、システム管理者タイプの支援が必要ですが、1 つの質問で割り引くことができます。それは、このクエリだけですか、それとも、多くの異なるクエリでこの効果を再現できますか?

が単なるクエリである場合、少なくとも 3 つの考えられる説明があります。

1つはデータ配信です。2 つのデータベースにデータがどのように取り込まれたか? 10g が 9i データベースからエクスポートされた場合、何らかの方法でソートされましたか? そうでない場合でも、ETL プロセスがデータを圧縮して整理し、アクセス時間を改善する方法で新しいインデックスを構築した可能性があります。

もう一つは統計です。10g の統計は新鮮で現実的ですが、9i の統計は古くて誤解を招くものですか?

3 つ目の可能性は、保存された実行計画です。(リテラルを含むクエリを投稿しました。これは、バインド変数を含むクエリにのみ適用されます。) 日付範囲の検索は、チューニングが難しいことで有名です。の日付範囲はto_date('30/10/2012', 'dd/mm/yyyy') AND to_date('31/10/2012', 'dd/mm/yyyy')1 つの種類の計画に適していますが、 の日付範囲はto_date('01/01/2010', 'dd/mm/yyyy') AND to_date('31/10/2012', 'dd/mm/yyyy') 別のアプローチに適している場合があります。9i データベースの既存の計画がより広い範囲に適している場合、狭い範囲のクエリには時間がかかる場合があります。


私がこれを入力している間に、あなたは説明計画を公開しました。キラー詳細は、9i プランの下部にあります。

Note: rule-based optimization

テーブルまたはインデックスの統計情報がないため、オプティマイザーは RBO のダム デフォルトを適用しています。これに本当に対処する必要がありますが、それは簡単な作業ではありません。すべてのテーブルの統計を収集する必要がある場合があります。init.ora ファイルの OPTIMIZER_MODE を変更する必要がある場合があります。データベース上のすべてのクエリの回帰テストを実行する必要がある場合があります。ですから、安易にやるべきことではありません。

それまでの間、このクエリに悩まされている場合は、ルールベースのオプティマイザーを昔ながらの方法で処理する必要があります。 詳細をご覧ください

于 2012-10-31T09:00:08.967 に答える
1

いくつかの観察:

  • あなたのインデックスはDESCENDINGインデックスです。これは関数ベースのインデックスであるため、RULE オプティマイザーでは期待どおりに機能しません。
  • 9i プランは OLD_IND でのみアクセスを示し、10g プラン (重要な述語ビットを切り取った) は範囲スキャン + インリスト イテレータを示しているため、その RED_PK によっては、おそらくより選択的な MEAS_ASS_ID でアクセスしている可能性があります。
  • インデックス作成に関しても、クエリに答えるために、WHERE OLD_IND = 0 AND MEAS_ASS_ID IN (5022, 5003) AND read_date BETWEENつまりOLD_IND equality, MEAS_ASS_ID equality and read_date range scanned, a better index is (OLD_IND , MEAS_ASS_ID , READ_DATE)、範囲スキャンを最後に実行して IO を削減します。
于 2012-10-31T12:13:41.483 に答える
0

2 つのサーバーのクエリで Explain を実行してみましたが、9i のクエリ オプティマイザーは 10g のものとは異なります。10g クエリ オプティマイザは、はるかに高速で並列化されています。次のリンクを確認してくださいクエリオプティマイザーのアップグレード

explain SELECT * FROM t_reading WHERE OLD_IND = 0 AND MEAS_ASS_ID IN (5022, 5003) AND read_date BETWEEN to_date('30/10/2012', 'dd/mm/yyyy') AND to_date('31/10/2012', 'dd/mm/yyyy');
于 2012-10-31T08:42:07.520 に答える