我々は次のクエリがあるとします。ORACLE SQL INDEX PERFORMANCE
select name
from friends
where upper(name) like UPPER('%ESC%') and age = 20;
インデックスそれへの最善の方法は何ですか?
CREATE INDEX fr ON friends (AGE,UPPER(NAME));
CREATE INDEX fr ON friends (AGE);
ありがとうございます。
我々は次のクエリがあるとします。ORACLE SQL INDEX PERFORMANCE
select name
from friends
where upper(name) like UPPER('%ESC%') and age = 20;
インデックスそれへの最善の方法は何ですか?
CREATE INDEX fr ON friends (AGE,UPPER(NAME));
CREATE INDEX fr ON friends (AGE);
ありがとうございます。
どのような方法が最適ですか? 2つはほぼ同等ですが、最初のクエリはクエリにとって非常に小さな利点があります。
like
パターンがワイルドカードで始まるため、上位レベルではage
のインデックスのみを設定できます。したがって、オラクルは、索引の最初の列であるage
が正しい年齢にあるすべてのユーザーを検索するために索引を使用できます。
注意してください。値がすでに索引に入っているため、最初の索引を持っている場合は、upper(name)
ファンクションを適用しないほどスマートになることがあります。オラクル社では、インデックス内のすべてのエントリをage = 20
にスキャンする必要がありますが、where
句のデータ・ページに移動する必要はありません。これは節約になる可能性がありますが、一般的には大きなものではありません。
クエリがあった場合:
where upper(name) between 'ESC' and 'FSC' and age = 20;
Oracleが直接インデックス内の適切な行を見ることができるので、その後、最初のインデックスが良いだろう。
おそらくどちらのインデックスもこのクエリで役に立ちません。
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))
のインデックスが維持管理のオーバーヘッドになる可能性があります。しかし、それが小さなテーブルである場合、またはあなたのすべての友人が大学時代のものである場合は、インデックスを気にする必要はありません。
要するに、ここにはさまざまな変数があります。できることはさまざまなオプションをベンチマークして、自分にとって最適なものを見ていくことです。