2

オラクルは、インデックススキャンではなくフルテーブルスキャンを実行する方が良いと「判断」することがありますが、まだ「学習段階」にあるため、「いつ」オラクルが最適なスキャンを決定するかをよりよく理解しようとしています。ルート。たとえば、単純なクエリがあります。

Select *
  FROM GLMV_JOURNAL_LOGS JLOG 
       INNER JOIN GLMV_Transact_Details TDTL 
          ON TDTL.TR_REF_NO = JLOG.TR_REF_NO 
         AND TDTL.SCAT_KEY = JLOG.Scat_key 
         AND TDTL.CASE_KEY = JLOG.CASE_KEY 
         AND TDTL.TR_CD = JLOG.TR_CD 
       INNER JOIN FUND_DESC FDDC 
          ON FDDC.FD_DESC_ID = TDTL.FD_DESC_ID  
       INNER JOIN FD_RATES FDRT 
          ON  FDRT.FDRT_KEY = TDTL.FDRT_KEY
       INNER JOIN BEN_TYPES BNTP 
          ON BNTP.BNTP_KEY = FDRT.BNTP_KEY 
 WHERE JLOG.JRNL_CD  = '0' 
   AND JLOG.SRC_CD = '2' 
   AND JLOG.MKEY_FD_NUM <> 0 
   AND NVL(JLOG.TMOV_KEY, -1) > 0 
   AND NVL(JLOG.ORIG_SCAT_KEY, 1) = 1 
   AND TDTL.STAT_CD <> '4' 
   AND NVL(TDTL.ORIG_SCAT_KEY, 1) = 1 

FD_RATES での結合は PK 値での結合です。テーブル全体のスキャンが防止されると考えて、GLMV_Transact_Details に対応するインデックスも作成しましたが、以下の説明プランに基づいて、インデックスの再構築を実行した後でもそうではありませんテーブルの統計を収集しても、結果は同じです。

計画の説明

ここで、クエリに次の where 句を追加するとします。

AND  FDRT.FDRT_KEY = 100

もちろん、インデックスは起動しますが、なぜ内部結合を行うときにそうでないのか、興味があると思います....何かヒントはありますか??

4

3 に答える 3

4

オプティマイザは、FD_RATES での全テーブル スキャンのコストを 106 と見積もっています。これがフィードされる結合は、その結合にフィードする他の行ソースと同様に、カーディナリティが 416 と見積もられます。ハッシュ結合をネストされたループに置き換えて、行ごとに一意のインデックス (PK) ルックアップを行う場合、コストはループの反復ごとに少なくとも 1、おそらく 2 または 3 になると考えられます。つまり、少なくとも 416 回、おそらくその 2 倍または 3 倍のコストがかかります。これは、完全なテーブル スキャンを実行する推定コストをはるかに上回ります。

さて、見積もりは間違っている可能性があります。私の経験では、主に確認すべきことは、計画に示されているカーディナリティです。これらが適度に正確である場合、Oracle が適度に効率的な結合順序とアクセス パスを選択した可能性が高くなります。必ずしも最も効率的ではありませんが、近いものです。

インデックススキャンを強制的に実行してパフォーマンスを確認したい場合は、次のヒントが必要だと思います。

Select /*+ INDEX(fdrt) */ *
...
于 2012-07-19T19:03:44.233 に答える
2

私はあなたの例を無視し、FTS とインデックスの質問に答えようとします :)

通常、インデックスを使用する理由は、クエリを満たすために読み取る必要があるデータ ブロックを最小限に抑えることです。これは、データがテーブルに物理的にどのように格納されるかによって大きく決まります。選択する行の割合に違いはありませんが、完全なテーブル スキャンの代わりにインデックスを使用することで回避できるブロックの数は変わりません。たとえば、3,000 ブロックにわたって 3,000 万行のテーブルがあり、15,000 行 (または .5%) を選択したい場合、インデックスを使用する必要がありますか? 15,000 行すべてが最後の 200 ブロックにある場合、インデックスは間違いなく意味があります。ただし、クエリで 15,000 行を取得するために各データ ブロックから 5 行を取得する必要がある場合は、とにかくすべてのブロックにアクセスする必要があるため、完全なテーブル スキャンの方が理にかなっています。

Cary Millsap は、Oracle インデックスを本のインデックスのように考える良い例を使用しています。オラクルに関する本を持っていて、「パーティション」を検索すると、おそらく比較的小さなページ セット全体で多くのオカレンスが示されます。したがって、この場合は、インデックスを使用することをお勧めします。ただし、「行」を調べると、「パーティション」と同じ数の出現がある可能性がありますが、それらはほとんどのページに広がっています。その場合、ページとインデックスの間を行ったり来たりするよりも、「フルスキャン」してすべてのページを順番に読む方がよいでしょう。

Oracle は、テーブル内のデータが物理的にどのように格納されているかについての概算をインデックスに格納し、選択するパスを決定するときにその情報を使用します。明らかに、これよりもはるかに多くのことがオプティマイザーに入ります (統計やパラメーターの設定が不適切であるとオプティマイザーが台無しになる可能性があります) が、これで作業を開始できます。

于 2012-07-19T19:59:40.960 に答える
0

完全な回答を得るには十分な情報がありませんが、ここにいくつかの発言があります。

  • あなたのような5テーブルの結合を単純とは呼びません。テーブルを空けてもらえますか?
  • テーブル全体のスキャンは、テーブルが大きい場合にのみ良くありません。小さいテーブルの場合、インデックス ベースのアクセスと違いはありません。
  • ヒント (コメントに埋め込まれている) を使用して、特定のアクセス パスを使用するようにオプティマイザに指示できます。
于 2012-07-19T18:45:16.983 に答える