2

テーブルを検討してください:

Table Name:ORDER
Columns: (ID (PK), ORDER_NUM, ORDER_STATUS, etc...)
Index(ORDER_IDX) exists on (ORDER_NUM, ORDER_STATUS) together.
There are various FKs too, on which Indexes exist as well.
There are about 2 million rows in the table.

SQL クエリを検討してください。

DELETE from ORDER where ORDER_NUM=234234;

特定の ORDER_NUM 値の場合、DELETE クエリの初回の実行は非常に遅くなります (200 行を削除するのに約 5 秒かかります)。

しかし、ロールバックして同じORDER_NUM に対して DELETE Query を再度実行すると、DELETE QUERY は 200 ミリ秒で実行されるようになりました。

したがって、このクエリに新しいORDER_NUM を指定すると、クエリの実行速度が非常に遅くなります。

初めてクエリ自体を固定するにはどうすればよいですか? インデックスを再構築する必要がありますか? それとも何か?

これをOracle SQLクライアントツール(TOAD/SQL-Developerなど)からテストしています-実際に使用されているWebアプリケーション内でこの遅い動作を見た後。

EDIT>>>
SET AUTOTRACE ON の結果

QUERY が実行される最初の時間

           3  user calls
           0  physical read total multi block requests
     4915200  physical read total bytes
     4915200  cell physical IO interconnect bytes
           0  commit cleanout failures: block lost
           0  IMU commits
           1  IMU Flushes
           0  IMU contention
           0  IMU bind flushes
           0  IMU mbu flush

クエリ実行時の 2 回目

           3  user calls
           0  physical read total multi block requests
           0  physical read total bytes
           0  cell physical IO interconnect bytes
           0  commit cleanout failures: block lost
           0  IMU commits
           1  IMU Flushes
           0  IMU contention
           0  IMU bind flushes
           0  IMU mbu flush

EXPLAIN プラン- FIRST RUN と SECOND RUN の両方でまったく同じです - 以下に示します。

    ID     OPERATION          NAME       ROWS    Bytes    Cost(%CPU)     Time<br>
=======================================================================================
    0      DELETE Statement               49     2891     41   (0)       00:00:01
    1      DELETE             ORDER      
    2      INDEX RANGE SCAN   ORDER_IDX   49     2891     3    (0)       00:00:01

初めてのときに、非常に高い物理読み取りが表示されます。
この状況を改善するために何かできることはありますか?

4

4 に答える 4

17

問題を理解するための鍵は、ステートメントがどのように実行されるかを理解することです。DELETE は比較的コストのかかる操作であり、多くの場合、パフォーマンスの問題につながります。したがって、Oracle が DML ステートメントを実行する方法は次のとおりです。

  1. DML を実行するための最初の手順は、必要なブロックをデータベース バッファ キャッシュで検索するか (既に存在する場合)、データファイルからバッファ キャッシュにコピーすることです (低速)。それに加えて、アンドゥ セグメントの空のブロックもバッファ キャッシュにコピーされます。
  2. 次に、影響を受ける行とインデックスにロックが設定されます。
  3. その後、やり直しが生成されます。データ ブロックと取り消しブロックに対して行われたすべての変更を記述する変更ベクトルが生成されます。DELETE の場合、元に戻すブロックに書き込まれる変更ベクトルは行全体です。
  4. 次に、DELETE が実行されます。行全体がデータ ブロックから元に戻すブロックにコピーされ、データ ブロック内の行が削除されます。たとえば、DELETE は INSERT よりもはるかに多くの元に戻すデータを生成します。これは、行全体の内容がコピーされるためです (そのため、他のセッションが元のデータを読み取ったり、削除をロールバックしたりできます)。

関連するすべてのブロックがすでにデータベース バッファ キャッシュにあるため、2 回目のクエリはほぼ確実に高速に実行されます。もちろん、データベース バッファ キャッシュに保持できるブロックが多いほど、必要な I/O は少なくなります。SGA のサイズが適切であることを確認してください。

したがって、あなたの問題については、次の点を確認する必要があります。

  • 最も重要なのは、クエリがインデックスを使用しているかどうかです。インデックスは有効ですか? DELETE クエリに対して EXPLAIN PLAN を実行し、ORDER_NUM のインデックスが使用されているかどうか、およびデータへのアクセス方法を確認します。
  • テーブルに制約はありますか? 「ON DELETE CASCADE」の CONSTRAINTS がある場合、DELETE の影響を受ける他のテーブルがある可能性があります。

したがって、あなたの問題については、実行計画 (EXPLAIN PLAN) を見ることが最善の策かもしれません。

于 2013-02-25T11:22:41.267 に答える
5

バッファー キャッシングの問題とは別に、パフォーマンスを向上させる 1 つの方法は、同じ ORDER_NUM を持つレコードの物理的なクラスター化を促進することです。これは、最も一般的に ORDER_NUM によってレコードのグループを選択する場合にのみ意味がありますが、(ORDER_NUM も含む子テーブルと共に) ハッシュ クラスター内にテーブルを作成することによって実現できます。

利点は、ORDER_NUM 述語を使用したクエリがアクセスするテーブル セグメントのブロックが少なくなるため、物理 I/O が必要な場合でも必要なブロックが少なくなることです。さらに、キャッシュされた各ブロックに関心のある行がより多く含まれるようにすることで、バッファ キャッシュをより効率的に使用し、キャッシュするブロックを減らすことができます。

于 2013-03-04T13:55:32.437 に答える
3

「初めて、非常に高い物理的読み取りを見ることができます。この状況で何か助けがありますか?」

クエリは、レコードをザッピングする前にレコードを見つける必要があります。レコードがメモリ内にある場合は高速で、ディスク上にある場合は桁違いに遅くなります。 詳細をご覧ください。 それが起こっていることです。初めて行を物理的に読み取るときは低速ですが、現在は行がDBバッファキャッシュにあるため、以降の読み取りは高速です。

最初の読み取りのパフォーマンスを向上させるために何ができますか?まあそれは時間がどこに行くかに依存します。何人かの人々があなたに説明計画を提供していないと尋ねているにもかかわらず。アクセスパスを知らなくても、具体的なアドバイスはあまりありません。それで、ここにいくつかのポインタがあります。

physical read total multi block requestsはゼロであるため、すべてがphysical read total bytes単一のブロック、つまりインデックス読み取りを表します。これには長い時間がかかるということは、インデックスが貧弱なものである可能性があることを示唆しています。チェックすることの1つは、インデックスのクラスタリング係数です。クラスタリング係数がブロック数に近い場合、インデックス範囲のスキャンは非常に高速になります。おそらく、削除で使用しているインデックスのクラスタリング係数が不十分です。そのため、説明プランが必要です。インデックスの品質を調査できるようにするためです。インデックスクラスタリングの詳細については、 TomKyteによるこの記事をお読みください。

クエリのクラスタリング係数が低い場合、調整できる量には制限があります。ことわざを磨くことはできません。削除するには行全体を取得する必要があるため、テーブルを読み取る必要があります。したがって、おそらく最も簡単なオプションは、テーブルの読み取りを高速化することです。

alter session enable parallel dml;

delete /*+ no_index (orders) 
           parallel */
from orders
where order_num=234234;  

11gを使用しているため、PARALLELヒントでオブジェクトを指定する必要はありません。並列操作にはEnterpriseEditionが必要であることに注意してください。

于 2013-03-02T09:07:23.520 に答える
-14

これは、テーブル/インデックスの断片化が原因である可能性があり、インデックスを介してデータにアクセスしているため、インデックスである可能性が高くなります。

テーブル レベルの場合、インデックスのみ (2) の場合、次の両方の手順が必要になります。

(1) テーブルの断片化に対処します。alter table "ORDER" move

(2) インデックスを再構築します。alter index "<YourIndex>" rebuild

多くの削除と挿入、または行の移行を引き起こす更新を行っている場合、これが当てはまる可能性があります。

于 2013-02-25T22:20:44.773 に答える