• 締切済み

前方一致で索引(インデックス)が使用されない?

社員表に対して、SQLを実行します。 (社員名)は任意の文字列です。 select syainNO from syain where deleteflg = '0' and syain_kubun = '2' and syain_mei like '(社員名)%'; 索引は以下の2つです。 // deleteフラグに対する索引・・・(a) create index syain_index_1 on syain ( deleteflg ) // 社員区分と社員名に対する索引・・・(b) create index syain_index_2 on syain ( syain_kubun, syain_mei ) deleteflgは0と1しか存在せず、0がほとんどです。 syain_kubunは1と2のみで、1が9割、2が1割程度です。 このとき、SQL実行時にトレースを分析すると、 (a)が使用され、(b)は使用されていません。 deleteflgとsyain_kubunのデータ分布からすると、deleteflg = '0'の条件により、 明らかに(b)の方が絞り込みを行えると思うのですが、使用されないのはなぜでしょうか? where syain_kubun = '2' and syain_mei like '(社員名%) ' and deleteflg = '0'; のように、条件の順番を入れ替えても効果はありませんでした。 試しにwhere句を変えてみると、(b)の索引が使用されます。 (likeをやめ、=を指定) where deleteflg = '0' and syain_kubun = '2' and syain_mei = '(社員名) '; この2つの違いは何でしょうか? 解決策として、以下を考えています。 (a)の索引は事情があって削除はできません。 (i)deleteflg = '0' を deleteflg != '1' にする  →(a)の索引が有効にならないようにする。   ただし、パフォーマンスに影響がないか (ii)deleteflg = '0' を条件から外す  →SQLを組み立てるjava側で、deleteflgの値によって   データ取得可否を判定するロジックが増えるのでちょっと。 これらの解決策に対するご意見、また、他に案がありましたら よろしくお願いします。

  • Oracle
  • 回答数2
  • ありがとう数0

みんなの回答

回答No.2

3つほど。 1つは b索引のカラム順序が悪いような気がします。 bの索引を使うとなるとまず1割程度までしか 絞込みを行えない社員区分での絞込みを行う必要があり、その分あまり効率のよい索引とはOracleはみなしません(その後の社員名で非常に少ない数まで絞り込めると分かっていても1つ目の絞込みが効率が悪ければOracleは候補からはずすことも十分に考えます。) ですのでb索引のカラム順序を逆にして社員名から 絞込みを行わすようにすればOracleが選んでくれる確立が高くなります。 社員区分は1割程度の絞込みしか行わないということで あまりOracleがこの索引を能動的に使うとは思えません。Oracleにといって1割もヒットするということは索引ではなく、全表走査の方が速いと決断することが多いです。 つぎにanalyzeをしっかりしてやるということです。 analyzeによってその表の中に何件のレコードがあって各カラムのデータ分布がどうなっているのかをしっかり把握できるのでより最適な実行計画をOracleが立てることができます。 最後に社員区分はNUMBER型ではないですよね? SQL文を見ると''で囲っているのでおそらくCHARか VARCHAR型だとおもうのですがここがずれていると またインデックスを使う可能性がなくなってきます。

回答No.1

バージョンもオプティマイザも不明なので、回答しにくいのですが・・ どの索引を使うか、はたまた索引を一切使わないか、などの判断は、 最終的にオプティマイザの決めることなので、オプティマイザが お望みの索引検索を行うと判断しやすいように方向付けすることしか 出来ません。 今回の場合、RBOでもCBOでも、オプティマイザヒントで索引を指定した方が 良い結果になるような気がします。(前置きのように確実な解決ではないけど) select /*+ INDEX(syain syain_index_2) */ syainNO from syain where deleteflg = '0' and syain_kubun = '2' and syain_mei like '(社員名)%'; としてみた場合、どうなりますか?

関連するQ&A

  • データベースの索引

    oracle masterの問題関連で質問があります。 一般的にデータベースで CREATE INDEX myind ON mytbl(a,b,c) と索引を作成した場合に SELECT a FROM mytbl ORDER BY a; この場合myindの索引は使用されるのでしょうか?

  • ORACLEのインデックスについて

    現在、ORACLE9を使用しているのですが INDEXについて理解できないことがあったので 教えてください。 組織、社員という2つしか項目を持たない 従業員という表があり600件ほどのデータがあります。 変更前は、 ・組織、社員にユニークインデックスは作成されていた。 ・600件ほどのデータの組織は全て同一。 となっており、その状態で select * from 従業員 where 組織 = 'ALL' and 社員 = '001' を流すとFULL SCANになっていました。 FULL SCANを回避できないかと思い、社員のみのインデックスを 追加し(* 一番下にインデックス追加時のSQLをはっています)  select * from 従業員 where 組織 = 'ALL' and 社員 = '001' を流すと追加したインデックスを読んでいました。 既に作成されていたユニークインデックスと異なるインデックスが 追加されたのかと思い、DBA_INDEXESの中を確認しましたが 異なっているのは、 ・UNIQUENESS ・INITIAL_EXTENT(ユニークインデックスは24576、  追加したインデックスは40960) ・LEAF_BLOCKS(ユニークインデックスは3、  追加したインデックスは2) の3点のみでした。 なぜこのような動きになるか理解できず、今後の対応に 迷っています。 ・原因 ・調査したらいい場所 ・参考資料 などがありましたら教えてください。 よろしくお願いします。 (*) インデックス追加時のSQL文は、create index 従業員A on 従業員 (社員) tablespace index storage (initial 40000 next 100000 maxextents unlimited pctincrease 0) pctfree 10となっています。

  • Oracleでルールベースでの複合索引

    数十万件のデータをバッチ処理を行っているのですが、パフォーマンスが悪く困っています。 その原因となりそうな部分について質問します。 テーブルAに複合索引を作ります。 create unique index uk_A on A(AA,AB,AC,AD); このテーブルに検索をかけます。そのときにWhere句に書く列の順序は、パフォーマンスには関係ないのでしょうか? select max(AD) from A where AA=1 and AB=2 and AC=3; としたときと select max(AD) from A where AC=3 and AB=2 and AA=1; としたときの、パフォーマンスの違いです。 このバッチ処理の中で、Aのテーブルに多数のデータを追加するために、コストベースにはできません。また、このSQL文は、プロシージャの中で使用しています。 範囲検索の場合のことは、講習でもあったのですが、等価結合のことは出てきませんでした。 どなたかご存知の方宜しくお願いします。

  • MySQLのUNIQUE INDEXとINDEX

    MySQLのUNIQUE INDEXとINDEXの使い分けで質問があります。 UNIQUE INDEXは、社員番号や学籍番号など重複がないものに対して使われ、 INDEXは名前のように重複が想定されるものに対して使われるのでしょうか? また、複数のカラムに同一のインデックスをつける場合、 CREATE INDEX idx_名前 ON 社員(氏,名) と言う感じになりますが 例えばこんなコード CREATE INDEX idx_名前 ON 社員(氏) and CREATE INDEX idx_名前 ON 社員(名) これはエラーになるんでしょうか?

    • ベストアンサー
    • MySQL
  • 目的のインデックスが使用されない・・。

    以下のSQLではインデックス1を使用してほしいのですがインデックス2が使われています。 インデックス1を使用されるように変更する方法を 教えてください。 インデックス1:「NO_UKE」「CD_STS」 インデックス2:「CD_STS」 select CD_STS from T_STS where NO_UKE = 10 and CD_STS = 7

  • 前方一致が動的に変更される場合にINDEXは有効になりません。

    いつもお世話になっております。 テーブル同士のLIKE検索(前方一致)を行った場合、 INDEXが有効になりません。 LIKE検索文字列を固定にした場合は、INDEXが有効 になります。 テーブル同士のLIKE(前方一致)でINDEXを 有効にする手段をご教授頂けないでしょうか。 以下、実行結果です。 (1)LIKE検索文字列が固定 ---------------------------------------------------------------------------- EXPLAIN SELECT * FROM wk_dss_data WHERE sys_id LIKE 'M004964%'; ---------------------------------------------------------------------------- Index Scan using i_wk_dss_data_02 on wk_dss_data (cost=0.00..5.25 rows=1 width=311) Index Cond: (((sys_id)::text >= 'M004964'::character varying) AND ((sys_id)::text < 'M004965'::character varying)) Filter: ((sys_id)::text ~~ 'M004964%'::text) (2)テーブル同士のLIKE検索 ---------------------------------------------------------------------------- EXPLAIN SELECT wk_dss_data.comp_id, wk_dss_data.user_id FROM wk_dss_data, t_update WHERE wk_dss_data.sys_id LIKE t_update.sys_id||'%'; ---------------------------------------------------------------------------- Nested Loop (cost=157.00..12505636.00 rows=2500000 width=20) Join Filter: (("outer".sys_id)::text ~~ (("inner".sys_id)::text || '%'::text) ) -> Seq Scan on wk_dss_data (cost=0.00..5479.00 rows=100000 width=31) -> Materialize (cost=157.00..207.00 rows=5000 width=11) -> Seq Scan on t_update (cost=0.00..157.00 rows=5000 width=11)

  • Indexについて

    初心者です。Indexについての質問です。 1.Where 注文No=nnn と 2.Where 注文No=nnn and 明細No=mmm といった問い合わせを行うため、二つのIndexを作成しました。 index-A:注文No index-B:注文No,明細No 「1.Where 注文No=nnn」の問い合わせは、 index-A、index-Bのどちらでもパフォーマンスは同じでしょうか? であれば、index-Aを消したいので・・・ よろしくご教授くださいませ。

  • Access結合後の短いテキスト型のインデックス

    Accessの検索にて、テーブルA LEFT JOIN テーブルB で外部結合し、 WHERE句でテーブルBの短いテキスト型を抽出条件にすると、検索が遅くなります。 【テーブル定義】 テーブルA( ・年月日(日付/時刻、重複ありインデックス) ・コード(短テキスト、重複ありインデックス) ・属性あ(短テキスト、重複ありインデックス) ・属性い(短テキスト、重複ありインデックス) ) テーブルB( ・コード(短テキスト、主KEY) ・属性う(短テキスト、重複ありインデックス) ・属性え(数値、重複ありインデックス) ) 【件数】 テーブルA:15万件 テーブルB:500件 =====SQLここから===== SELECT * FROM テーブルA LEFT JOIN テーブルB ON テーブルA.コード = テーブルB.コード WHERE 属性あ IS NULL AND 属性い = 'あああ' AND 属性う = 'アアア' AND 属性え = 1 GROUP BY 年月日、 属性う =====SQLここまで===== この検索SQLは遅い(1分30秒くらい)のですが 『AND 属性う = 'アアア'』を削除すると 10秒くらいに速くなります。 ”属性う” のインデックスが効いてないように見えるのですが どのようにチューニングしたら速くなるでしょうか? エクセルからLAN越しにDAO接続してSQL実行してます。 AccessはOffice365(バージョン1902)です。

  • 最適なインデックス作成

    いつもお世話になってます。 下記のSQLがあるとします。 SELECT A.COL3, A.COL4, B.COL5, SUM(A.COL6) -- (5) FROM TABLE1 A INNER JOIN TABLE2 B ON A.COL1 = B.COL1 -- (2) WHERE -- (1) A.COL1 = '1' AND A.COL2 = '2' GROUP BY A.COL3 ,A.COL4 -- (3) ORDER BY A.COL3, A.COL4 -- (4) 番号はSQLが内部処理(絞りこみやソート)される順番とも考えています。 この場合にてインデックスを作成する場合 「TABLE1 A」に IND1(A.COL1,A.COL2,A.COL3,A.COL4,A.COL6) ON TABLE1 の複合インデックスを作成すべきか、それとも番号単位に個別に索引を作成した方が良いのか悩んでいます。 番号単位だと例えば IND1(A.COL1,A.COL2) IND2(A.COL3,A.COL4) IND3(A.COL6) アドバイスなどあればよろしくお願いします。

  • インデックス名の重複(MySQL5.1+Windows2008)

    インデックス名の重複(MySQL5.1+Windows2008) テーブルを次のSQLでコピーしました。 mysql>create table 新テーブル名 like 元テーブル名; インデックスもコピーされたのですが、インデックス名が重複します。 これは、問題ないのでしょうか? 新テーブルにも、同じインデックスを張りたいので、問題がなければこのままにしておきたいと思っています。 よろしくお願いします。

    • ベストアンサー
    • MySQL