• ベストアンサー

パフォーマンスについて

現在1つのSQLで10秒程度かかります。 データが700万件あるのでそれが原因というのもありますが、それにしても遅いです。 以下のSQLです。 select CD_STS from T_STS where NO_UKE = '20000' and CD_STS = '07' インデックスに「NO_UKE」と「CD_STS」で作成しています。 なにかいい方法はありませんか?

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

質問者が選んだベストアンサー

  • ベストアンサー
  • guchi32
  • ベストアンサー率100% (10/10)
回答No.2

オプティマイザはルールベースですか? コストベースならば、アナライズしてみてはいかがでしょうか。 コストベースオプティマイザでは、アナライズの結果を元に実行計画を考えます。データが少ないときしかアナライズしていなければ、オプティマイザは「インデックス検索より全件検索の方がコストが低い」と判断する場合があります。 ハードウェアのスペックにもよりますが、実行計画でインデックスが正常に使われているようであれば、下記を考えてみてはどうでしょうか。 ・パラレルヒントの追加   → 検索命令を同時に複数出します。 ・I/O関連の初期化パラメータ変更   よく行うのが「db_file_multiblock_read_count」の変更です。OSによって理論値は変わりますが、4~64の範囲程度で変更してください。ただし、他のSQLにも影響しますので、十分にテストを行う必要があります。 ・表の再編成   → 行連鎖や行移行が発生している可能性があり、ブロックを複数読んでいる可能性があります。EXPORT+IMPORTやCreate AS Selectで再編成が行えます。 ・インデックスの再編成   → 範囲検索ではないので、あまり関係ないかもしれませんが・・・いちばん簡単です。(REBUILDするだけです) ・表のパーティション化   → OracleEEのパーティションオプションが必要ですが、HASHパーティションにするだけでもかなりの効果があると思われます。

toshi_200578
質問者

お礼

詳しく説明して頂いてありがとうございます。 調べた結果、目的のインデックスが使われていませんでした。 知識不足でオプティマザ自体が理解してなくわかりませんでした。 オプティマザヒントというものを使って目的のインデックスを使用させるようにできると聞きましたので方法を調べてみます。 ありがとうございました。

その他の回答 (1)

回答No.1

「NO_UKE」と「CD_STS」の複数項目による索引があるということでしょうか? それとも、それぞれ単一項目の索引で、2つ索引があると言うことですか? オラクルは、複数の索引を使って、クロスマッチするような絞り込みは行わなわず、 1つの索引で、より絞り込める側の索引を選択する努力をします。 単一項目の索引なら、複合項目(NO_UKE+CD_STS)の索引を作る方向で検討するのが一番です。 既に複合項目で索引を作っているなら、正しく索引が使われているか実行計画にて確認してください。 可能性として、何らかの理由で、索引が使われていないため、検索が遅いと言うこともありますので。 もし、最適な索引が使われていないようでしたら、ルールベースなら、オプティマイザヒントで索引を 使うよう指示してください。 コストベースなら、統計情報の再収集で改善されると思います。

toshi_200578
質問者

お礼

複数項目の索引1と単一項目「CD_STS」の2つの索引2があり、索引1を使ってほしいのですが索引2が使われていました。 なにぶん知識不足でルールベースならオプティマザヒントで指示できるのですね。 (オプティマザヒント自体よく理解していませんが。。) もう少し調べてみます。 ありがとうございました。

関連するQ&A

  • パフォーマンスについて

    次の2つのSQLで10秒前後の開きがあります。 原因は「CD_STS」なのですが、理由がわかりません。 データは700万件あります。 インデックスは「NO_UKE」と「CD_STS」につけています。インデックスは全部で5つあります。 なぜこれほど違いがでるのでしょうか? 原因がわかったのでお客さんに説明したいのですが理由がわからなくて困っています。。 考えられそうな理由があればお願いいたします。 ■即■ select CD_STS from T_STS where CD_KAIIN = 50 and FL_DEL = 0 and NO_UKE = 10 and (CD_STS <= 7 and CD_STS >= 7) ■10秒前後かかる■ select CD_STS from T_STS where CD_KAIIN = 50 and FL_DEL = 0 and NO_UKE = 10 and CD_STS = 7

  • 目的のインデックスが使用されない・・。

    以下の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

  • 性能の改善について

    以下の(1)のSQLと(2)のSQLで性能が全然違います。原因は明示的に「1」を取得するようにしているからなのですが、改善する方法はないでしょうか? (1)SQL(遅い) SELECT 1, /*+ INDEX(T_UKERUI T_UKERUIP1) */ T.NO_UKE FROM T_UKE T ,M_OFF O ,M_KAI K WHERE T.CD_OFR = O.CD_OFR AND T.CD_KAIIN = K.CD_KAIIN AND T.CD_STS IN (3, 4) AND T.CD_SHIP = 0001 AND T.NO_ADDNO = 0 (1)SQL(速い) SELECT /*+ INDEX(T_UKERUI T_UKERUIP1) */ T.NO_UKE FROM T_UKE T ,M_OFF O ,M_KAI K WHERE T.CD_OFR = O.CD_OFR AND T.CD_KAIIN = K.CD_KAIIN AND T.CD_STS IN (3, 4) AND T.CD_SHIP = 0001 AND T.NO_ADDNO = 0

  • sqlのwhereで指定した条件の前後を取得したい

    テーブル=T) KEY DATA 001 あ 002 い 003 う 004 え 005 お SQL) SELECT DATA FROM T WHERE KEY = 003 ; 上記のSQLでは、「う」のデータしか取得できませんが、 「003」の前後1件、合計3件の「い」「う」「え」を取得する方法を教えて下さい。 ちなみに、 SELECT DATA FROM T WHERE KEY >= 003 AND ROWNUM <= 2 と SELECT * FROM ( SELECT DATA FROM T WHERE KEY < 003 ORDER BY KEY DESC ) WHERE ROWNUM < 1 のUNIONでは上手く行きませんでした。 よろしくお願いします。

  • sedに関する質問

    ★以下のファイルがあるとします。 SQL> select count(*) from koumoku where no = 1052 and mid =2; COUNT(*) ---------- 7 SQL> select count(*) from koumoku where no = 1053 and mid =3; COUNT(*) ---------- 4 SQL> select count(*) from setumei where no = 1054 and mid =2; COUNT(*) ---------- 9 SQL> select count(*) from setumei where no = 1055 and mid =7; COUNT(*) ---------- 5 SQL> select count(*) from imi where no = 1056 and mid =2; COUNT(*) ---------- 9 SQL> select count(*) from imi where no = 1057 and mid =6; COUNT(*) ---------- 3 ★ここでsedコマンドを利用して、 koumoku COUNT(*) ---------- 7 koumoku COUNT(*) ---------- 4 setumei COUNT(*) ---------- 9 setumei COUNT(*) ---------- 5 imi COUNT(*) ---------- 9 imi COUNT(*) ---------- 3 のように取り出したいのですが、方法が分からないので、 誰か教えてもらえますか?宜しくお願いします。

  • WITH句を使用したSQLの結果

    WITH句を使用して総件数と1~20件までのデータを同時に取得するSQLを組んでみたところ、 WITH TMP AS (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO) SELECT T1.ALLCNT, T2.* FROM (SELECT COUNT(*) ALLCNT FROM TMP) T1, TMP T2 WHERE T2.CHECKROWNUM BETWEEN 1 AND 20; Oracle10.2.0.3.0のバージョンで ALLCNTが21になってしまう現象が発生してしまいました。 Oracle10.2.0.4.0や9iでは発生せず正しい総件数が取得できるのですが、 バージョンによる不具合は考えられますでしょうか。 それともSQL自体なにか悪い部分があるのでしょうか。 ちなみに T2.CHECKROWNUM BETWEEN 1 AND 100; と帰るとALLCNTが101と帰ってきます。 また、WITH句を使わず下記のようにTMPの部分をWITH句で使用したSQLに 置き換えると正しくALLCNTが取れます。 SELECT T1.ALLCNT, T2.* FROM (SELECT COUNT(*) ALLCNT FROM (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO)) T1, (SELECT ROW_NUMBER() OVER (ORDER BY NO) AS CHECKROWNUM,NAME FROM TEST_TBL ORDER BY NO) T2 WHERE T2.CHECKROWNUM BETWEEN 1 AND 20;

  • SQL文でのデータの取得が上手くいきません

    初めて質問させていただきます。 こちらのカテゴリで良いのか分からなかったのですが、よろしくお願いいたします。 SQL文を作成しているのですが、上手くいかず困っている状況です。 要件としてはテーブルAにユーザーの情報が格納されているのですが、 キーの一つとして世代(SEDAI_NO)(日付)を持っております。 今回取り出したいデータは該当ユーザーの処理日以前の最新のデータを 取得したいと思い以下のSQL文を作成しましたが、上手く行かず、最新世代を含むそれ以前の世代のデータを取得してきています。 どこがおかしいのでしょうか? よろしくお願いいたします。 【作成したSQL】 select * from テーブルA テーブルA’ where (USER_ID=該当のユーザーID) and (SEDAI_NO = (select max(SEDAI_NO) from テーブルA where SEDAI_NO = テーブルA’.SEDAI_NO AND 処理日 >= テーブルA'.SEDAI_NO)

  • PL/SQLでログを確認したい。

    以下のPL/SQLで取ってきた値をログか何かで確認したいのですが、いい方法がありますか? 想像では5行目あたりにログはきだす記述をするのかなと思うのですが、方法がわかりません。 どなたか教えてください。 -------------------------------------------- 1select count(*) into vn_CNT from t_ukerui 2 where no_toi = :new.no_toi 3 and no_uke = :new.no_kyaku 4 and no_gyo = 1; 5 6if ( vn_CNT > 0 ) then 7 --------------------------------------------

  • あいまい検索のパフォーマンス向上について

    あいまい検索(部分一致)検索をする際に、あいまい検索だとインデックスも効かないので、インデックスを張ってパフォーマンス向上という訳にもいかず、パフォーマンスが非常に悪くて困っています。 状況としては、WEBアプリケーションで、検索画面から検索条件を入力し、「Find」ボタンを押下するとJavaでSQLを発行し、Oracleへ接続するという仕組みのシステムです。 下記のようなケースで、後者のSQLに変更するとガツンとパフォーマンスが向上したのですが、偶然でしょうか? 【もともとのSQL】 select name ,age ,sex ,blood_type ,address from TABLE1 where age >= 20 and age < 30 and blood_type = 'A' and name like '%山%' and address like '%中央区%' / 【パフォーマンスが向上したSQL】 select * from (select name ,age ,sex ,blood_type ,address from TABLE1 where age >= 20 and age < 30 and blood_type = 'A' ) where name like '%山%' and address like '%中央区%' / というふうに、あいまい検索部分を別出ししました。 WHERE句の条件をANDでたくさんつなげる際に、2度の問い合わせにはなりますが、一度あいまい検索以外の条件で絞り込んで、それから再度その結果に対してあいまい検索を実施した方が早いのではないかと思ってやったところ実際に早くなったのですが、これは偶然でしょうか? 件数が増えると逆に遅くなるとかだと、逆効果なので、理論的にはどうなのか、ご存知の方がいらっしゃったら教えてください。 また、実際にはテーブルではなく、VIEWに対しての検索で実施しました。 よろしくお願い致します。

  • Oracle8での外部結合

    現在、oracle8.1.7で開発しています。 T1,T2,T3の3つのテーブルがあります。 T1のデータで、T3のテーブルにまだデータが存在しないものを検索しています。 それは既にできました。 次に、条件として、  (1)T1のA,B,Cと一致し、かつFLGが5または9  (2)T1のA,B,Cと一致するデータがない。 という2点を追加しました。 しかし、以下のようにFLGが1となっているものまで検索してしまいます。   <T1>        <T2>      <T3> A:あいうえお     A:あいうえお    データ無し B:bbb        B:bbb C:ccc        C:ccc             FLG:1   ===SQL文============================================================== SELECT A,DT1,DT2 FROM T1 WHERE A LIKE 'あ%' ---追加部分---- AND ( EXISTS (SELECT A FROM T2 WHERE A=T1.A AND B=T1.B AND C=T1.C AND FLG IN (5,9)) OR NOT EXISTS (SELECT A FROM T2 WHERE A=T1.A AND B=T1.B AND C=T1.C ) ) ----ここまで---- AND NOT EXISTS (SELECT * FROM T3 WHERE KATAMEI='あ' AND NO=1) どこがいけないのでしょうか? よろしくお願いしますm(_ _)m