2016-04-02 9 views
-1

我々は次のクエリがあるとします。ORACLE SQL INDEX PERFORMANCE

select name 
from friends 
where upper(name) like UPPER('%ESC%') and age = 20; 

インデックスそれへの最善の方法は何ですか?

  1. CREATE INDEX fr ON friends (AGE,UPPER(NAME));
  2. CREATE INDEX fr ON friends (AGE);

ありがとうございます。

答えて

1

どのような方法が最適ですか? 2つはほぼ同等ですが、最初のクエリはクエリにとって非常に小さな利点があります。

likeパターンがワイルドカードで始まるため、上位レベルではageのインデックスのみを設定できます。したがって、オラクルは、索引の最初の列であるageが正しい年齢にあるすべてのユーザーを検索するために索引を使用できます。

注意してください。値がすでに索引に入っているため、最初の索引を持っている場合は、upper(name)ファンクションを適用しないほどスマートになることがあります。オラクル社では、インデックス内のすべてのエントリをage = 20にスキャンする必要がありますが、where句のデータ・ページに移動する必要はありません。これは節約になる可能性がありますが、一般的には大きなものではありません。

クエリがあった場合:

where upper(name) between 'ESC' and 'FSC' and age = 20; 

Oracleが直接インデックス内の適切な行を見ることができるので、その後、最初のインデックスが良いだろう。

1

おそらくどちらのインデックスもこのクエリで役に立ちません。

AGEは非常に選択的なようです。 100以上の異なる値があります(樹木や建物を友人として除外できると仮定した場合)。したがって、AGEの検索では、すべての可能なレコードの〜1%を探しているように見えるかもしれません。ただし、AGEは均等に分散されていません。AGE=20のフィルタは、AGE=99より多くのレコードを返す可能性があります。

UPPER(NAME)は、like UPPER('%ESC%')に制限しています。 CESCはESCOBARとFRANCESCAのように一致します。だから、クエリはすべての名前を評価する必要がありますAGE=20。インデックスがfriends (AGE,UPPER(NAME))の場合、インデックス範囲スキャンを使用してWHERE句全体を評価することができますが、これはかなり効率的です。インデックスがAGEの場合、この時点でテーブルが読み取られます。

どちらの方法でも、ではなく、UPPER(NAME)を返すため、クエリでテーブル全体を取得する必要があります。 AGE=20に多くのヒットがある場合は、多くのインデックス付き読み込みのコモンネーム要素が高価です。 FRIENDSが非常に広いテーブル(カラム数が多い)でない限り、テーブル全体を読み取るフルテーブルスキャンは効率的です。

パフォーマンスチューニングはトレードオフの問題です。友人に多くのレコードがあり、年齢が良好なの場合、AGEとUPPER(NAME)を頻繁に照会したい場合は、friends (AGE,UPPER(NAME))のインデックスが維持管理のオーバーヘッドになる可能性があります。しかし、それが小さなテーブルである場合、またはあなたのすべての友人が大学時代のものである場合は、インデックスを気にする必要はありません。

要するに、ここにはさまざまな変数があります。できることはさまざまなオプションをベンチマークして、自分にとって最適なものを見ていくことです。