2

私はこのようなクエリを実行していますが、完了するまでに6秒かかります:

select * 
from ( select aaa."ID" 
      from "aaa"  
      where aaa."DELETED" is null 
      order by aaa."CREATED" desc ) 
where rownum <= 15;

テーブルに約 160 万のレコードがあり、削除された列と作成された列に別のインデックスを追加しようとしました。作成された列と削除された列の両方を含むインデックスを追加して、同じインデックスを作成しようとしました。別の順序で。何も役に立たないようです。これをスピードアップするにはどうすればよいですか?

休止状態によって生成されるため、クエリをあまり変更できません

編集:クエリがなくaaa."DELETED" is nullても実行が非常に遅くなります。

編集2: クエリ プラン

編集 3: インデックス定義を追加します。正直なところ、これらの数字のほとんどが何を意味するのかわかりません。インデックスの作成に sqldeveloper を使用しています。各インデックスに非常に多くの構成オプションがあることさえ知らなかったので、ドキュメントを調べます。

CREATE INDEX "aaa"."aaa_CREATED_ASC" ON "aaa"."aaa"
  (
    "CREATED"
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;
CREATE INDEX "aaa"."aaa_CREATED_DESC" ON "aaa"."aaa"
  (
    "CREATED" DESC
  )
  PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE
  (
    INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT
  )
  TABLESPACE "SYSTEM" ;
4

2 に答える 2

9

Oracle がデータベース内のレコードにアクセスする方法を理解する必要があります。インデックスの読み取りは 1 つのアクションであり、テーブルの読み取りは別のアクションです。したがって、テーブルから 1 つのインデックス付きレコードを取得するには、少なくとも 2 回の読み取りが必要です。

クエリでは、次の 3 つの情報を使用します。

  • DELETED 列 (制限基準)
  • CREATED 列 (ソート基準)
  • ID (結果セット)

Oracle は NULL 値のインデックスを作成しないため、単一列のインデックスでDELETEDは役に立ちません。これはテーブル全体のスキャンであり、インデックスがまったくないことに勝るものはありません。

CREATEDアクセス パスが次のようになるため、単独のインデックスの方が適しています。

INDEX FULL SCAN DESCENDING

つまり、インデックスの最新の日付から開始し、逆方向に動作します。ただし、クエリは ID と DELETED 値を見つけるためにテーブルを読み取る必要があります。DELETED が null である頻度によっては、大量のテーブル読み取りが発生する可能性があります。

Oracle は列内の NULL にインデックスを付けるようになる(CREATED, DELETED) ため、この順序での複合インデックスがより便利になるはずです。DELETEDOracle はインデックスを使用して、ID値を取得するためにテーブル レコードのみを参照するようにできます。これは、15 回のテーブル読み取りになります。

最後に、複合インデックスを作成し(CREATED, DELETED, ID)、インデックスからクエリ全体を処理できます。それはまだ最速のオプションです。

次に、パフォーマンス上の利点がインデックスを維持するオーバーヘッドを正当化するかどうかを判断する必要があります。それだけの価値があるため、複合インデックスを維持するコストは、単一列インデックスを維持するコストにわずかな割合を追加します。


ちなみに、このような恐ろしいクエリは、論理削除を使用するのが悪い考えである理由の 1 つです。レコードを物理的に削除し、ジャーナル テーブルを使用して、必要に応じてテーブルの履歴状態を取得します。

于 2011-11-08T14:20:24.383 に答える
-1

ここを見てみてください

http://www.dba-oracle.com/oracle_tips_null_idx.htm

また(ここで役立つとは思えませんが)、生成されたクエリが遅すぎる場合に備えて、休止状態のネイティブクエリがあります。

于 2011-11-08T13:39:49.840 に答える