インデックスを使わないSQLはパフォーマンスが遅いOracleでパフォーマンスが遅いのにはいくつかの理由があります。パフォーマンスが遅い理由で最も多いのが「SQLの問題」です。SQLを改善すれば、パフォーマンスがよくなって検索時間を短縮でき >GROUP BY句などその他には一切変更はないということであれば ・セッション単位ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4 ; ・ヒントSELECT /*+ PRALLEL(4) */ a. * FROM TAB1 a,TAB2 b WHERE a.COL1 = b.COL1, ・テーブル結合の順序を任意に決めたい場合のヒントSELECT /*+LEADING(b,a)*/ a.   T20.AAAA sql> select * from tab1 where c1 = 100 2 union all 3 select * from tab1 where c2 = 200 4 union all 5 select * from tab1 where c3 = 300; これについては、オプティマイザがor-expansion(or拡張)として自動的に行ってくれるようになっています(以下のように実行計画にconcatenationと出力され …   CASE WHEN ISNULL(T20.BBBB,'') = '' THEN '' ELSE FORMAT(T20.BBBB,'yyyy/MM/dd') END AS BBBB Powered by WordPress with Lightning Theme & VK All in One Expansion Unit by Vektor,Inc. sqlって奥が深いっすね 楽天の item と category を JOIN するところでなんか重いな〜と思って色々試してた。 item は id がユニークなキーになっているんだけど、category は一つの item に対して複数のカテゴリーを設定できるから、   CASE WHEN ISNULL(T20.AAAA,'') = '' THEN '' ELSE FORMAT(T20.AAAA,'yyyy/MM/dd') END AS AAAA ここでは、UNIONを使ったSQLをチューニングする方法を紹介します。UNIONとは複数のSELECT結果を結合することが出来ます。SELECT結果を結合するとき、重複する行データは削除されます。つまり同じデータが2件あると1件は削除され、1件だけが残ります。<SQLの例>select * from test1unionselect * … SQLの実行結果において、 式を加えると、非常に遅くなりますが、どのように変更すれば良いのかご教示頂きたく 投稿させて頂きます。 実行結果が12秒程度で返ってくるクエリ。 Select T20.AAAA T20.BBBB From CCCC T20 実行結果が80秒程かかるクエリ * FROM TAB1 a,TAB2 b WHERE a.COL1 = COL2, 例えば、データの変更はほとんど発生しないが、オンライン処理などで何度も呼び出されるようなマスタなどは、予め、キャッシュにインプットしておきます。そして、キャッシュからアウトプットされないように、設定しておくことができます。, 具体的には、バッファキャッシュ領域のうち、いくらかをKEEPバッファキャッシュ領域として割り当てます。そして、対象となるテーブルの属性をKEEPにします。後は事前にSELECT文を実行するなどして、キャッシュにインプットします。※こちらもデータベースサーバのキャッシュサイズに関わる変更なので、導入検討する場合はDBAに相談してください。システムによっては、JAVA側でCACHEする仕組みもあると思います。必ずしもデータベース側での対応が必須ではありません。, ・KEEPバッファキャッシュの指定alter system db_keep_cache_size 5G, ・テーブル属性の変更ALTER TABLE tab1 BUFFER_POOL KEEP※デフォルトに戻す場合は、ALTER TABLE tab1 BUFFER_POOL DEFAULT, SELECT文をチューニングする方法を5つ紹介しました。 1.インデックスの作成 2.ヒントの追加 3.パラレル実行 4.SQLの書き換え 5.バッファキャッシュの活用, SQLの遅い原因は多岐に渡ります。よくある原因は↓で紹介していますのでぜひ参考にしてください。>>SQLが突然遅くなる原因と対応方法.  From CCCC T20, Select IN演算子の後にサブクエリがある場合、SQLはサブクエリから実行されます。一方 EXISTS演算子の後にサブクエリがある場合でも、メインクエリから実行されます。 例 下記のテーブルを例にします。 products; id model name category price; 1: C-XM01: モーダンチェア: チェア: 56000: 2: X-XD05: ラージデ … select文をチューニングする方法を5つ紹介しました。 1.インデックスの作成 2.ヒントの追加 3.パラレル実行 4.sqlの書き換え 5.バッファキャッシュの活用.  From CCCC T20, 上記クエリは簡易的に記載していますが、 * FROM TAB1 a,TAB2 b WHERE a.COL1 = b.COL1, SQLの書き方は自由度が高く、結果として同じデータを抽出するSQLでも、書き方が異なるケースがあります。そういった場合は、出来るだけ、効率よく、高速にデータを抽出できる書き方に変更しましょう。. 実際には、テーブル結合を20個以上行い、取得項目も30個程度あります。, 実際のクエリ + 問題となっているフィールドに対して、 ・IN句をEXISTS句に置き換え(変更前)select * from table1 a where a.div_cd in (select b.div_cd from table2 b where b.div_name = ‘IT’); (変更後)select * from table1 awhere exists (select ’x’ from table2 b where b.div_name = ‘IT’ and a.div_cd = b.div_cd); ・OR句の置き換え(変更前)select * from table1 awhere a.div_cd = ‘100’ OR a.div_cd = ‘200’; (変更後)select * from table1 a where a.div_cd = ‘100’union allselect * from table1 a where a.div_cd = ‘200’; ・IN句の置き換え(変更前)select * from table1 a where a.div_cd in (‘100′,’200’); 続いては、データベースサーバーのリソースを最大限に活用してチューニングする方法です。リソースに余裕があるのであれば、ORACLEのパラレル機能を活用してください。, これはセッション単位もしくはSQL単位に実行することができ、ORACLEデータベースの内部的プロセスを使って、SQLでのデータ抽出を並列実行することが出来ます。, ※一歩間違えるとデータベースサーバー全体のリソースを消費しトラブルになりかねないので、お近くの上位SEやDBAに相談の上、利用してください。. sqlを速くするぞ ... ・チューニングに関する全体の方針を述べておくと、それはボトルネック(一番遅いところ)を改善することです。当たり前ですが、既に十分速い処理をもっと速くしたところで、システム全体のパフォーマンスには影響しません。 80秒程掛かります。, 問題となっている対象フィールドに対して、 SQLの実行結果において、 ここではORACLEデータベースのSQLで、SELECT文をチューニングする方法を紹介します。, SQLの実行計画の見方や確認方法については↓で紹介していますので参考にしてください。>>【ORACLE】SQLの実行計画の見方>>【ORACLE】SQLの実行計画を取得する方法, SELECT文をチューニングする方法を5つ紹介します。 1.インデックスの作成 2.ヒントの追加 3.パラレル実行 4.SQLの書き換え 5.バッファキャッシュの活用以降でより詳しく解説していきます。, インデックスを作成することで、レコードの抽出にかかる時間を短縮することが出来ます。またインデックスはSQLを変更する必要がないので、プログラムのコードを変更する必要もありません。, インデックスの列にはWHERE句の条件で、抽出条件として書かれているものを書くと効果的です。詳しくは「【SQL】インデックスの項目の順番の正しい付け方」で解説してありますので参考にしてください。, インデックスが使用されると、フルスキャンからインデックスレンジスキャンへと実行計画が変化します。–TABLE ACCESS BY INDEX ROWID table1—-INDEX RANGE SCAN IX_table1_001, SQLは狙い通りに、効率良く実行されないケースがあります。例えば、次のようなケースです。・インデックスを作成したけど、インデックスが使われない・テーブルの結合順序が狙い通りにならない・たまに遅いときがある・急に遅くなる時がある, 原因は多岐に渡ります。例えば、次のようなことがあります。・統計情報が最新でない・SQLが複雑すぎるあまり、適切な実行計画が作成されない・データの増減によって、実行の都度、実行計画が変わってしまう, こういったケースでは、ヒントが有効です。ヒントを書き足すことで、実行計画をある程度、狙い通りに変更することが出来ます。※ヒントは名前の通り、”ヒント”ですので、絶対に変更される訳ではありません。. sql クエリの改善、サーバー設定の見直しといった2パターンがあり、どちらも重要な要素です。 データベースが全体的に遅い場合はサーバー側の設定、 特定の処理のみ遅い場合は sql クエリの改善から先に着手することをオススメします。 式を加えると、非常に遅くなりますが、どのように変更すれば良いのかご教示頂きたく 環境 SQL Server 2014. 現代社会において私たちは頻繁にスマホアプリやWebサービスを利用しており、アプリなしでの生活は考えられなくなりました。「あ~もうっ、アプリの動作が遅くてイライラする。」と思ったことはないでしょうか?この原因には様々な理由が考えられますが、原因の一つに、アプリで利用しているSQLの品質が悪いということが考えられます。, SQLはデータベースを操作する際に使用する言語で、このSQLの書き方が悪いとアプリの動作に影響を与えます。そのため、プログラマーにはパフォーマンスの良いSQLを書くスキルが必ず求められます。この「SQLを改善する作業」は「SQLチューニング」と呼ばれています。今回はこのSQLチューニングに関して説明します。, ではなぜアプリのパフォーマンスが悪いことが問題になるのでしょう?「動作が遅くても最終的に動いてくれれば別にいいのに・・・。」という考えも一部ではあるかもしれません。しかし、それは大きな間違いで、速度はアプリが想定通り動作するかどうかと同じくらい重要なことです。時にアプリは、「速度が遅い」という理由で使われなくなってしまいます。, 速度を改善するということはシステム開発を行う上で非常に重要です。企業の基幹システムは機能ごとに目標の応答時間があり、それを達成できないと不具合として扱われ、リリースが延期になったりすることもよくあります。, SQLチューニングはほぼすべてのシステム開発で求められる作業ですが、実は非常に高度な作業であるため、この作業をこなすにはスキルと経験が必要になります。, たとえば、システム内で画面に表示する情報を取得するSQLを速度改善するケースで考えてみましょう。, SQLが複数のトランザクションテーブルを結合している場合、結合の部分の影響で遅くなっていることがあります。結合はそれなりに重い処理になるので、結合せずにSQLを書くと改善するケースが多いです。作業画面に必要なデータだけを集めた参照用のテーブルを新しく作成し、そのテーブルからデータを取得するようにすると解決することがあります。, 解決方法は、一つではありません。この例だと、新たにテーブルを作ることになるので、後でシステムへの機能追加のためテーブルにカラムを増やす必要がある場合、トランザクションテーブルと参照用のテーブルの両方にカラムを足すことになり、ダブルメンテナンスになります。このような保守性の低下以外にも、SQLチューニングは方法を間違うと逆効果になることもあります。データベースに関する高度な知識と未来に起こりえる変更にも柔軟に対応できる経験が必要になってきます。, SQLチューニングの方法は無数にありますが、大きく分けると2種類に分けられます。「現在のSQLの無駄な部分が無いか調査し改善すること」と、「表面には出ていない問題点を調査し改善すること」です。, ・select * from ~となっている部分が無いか探し、あれば必要なカラムだけ取得するようにする, *はテーブルの全項目を取得するという意味。必要な項目だけを指定することで、アプリに送られるデータ量が少なくなり速度改善が見込めます。, 不具合修正や追加開発時などでもともと結合されていたテーブルが必要なくなっていることがあります。, ・「in句」で実装されている部分を「exists句」で実装できるかどうか検討してみる, exists句はすべてのレコードを検索する必要が無いので速度改善できることがあります。, 対して、二つ目の表面に出ていない問題点の調査と改善は、システム全体に影響することもあるので、高度なスキルが必要です。, まずは利用されているSQLを分析し、問題点を洗い出す作業を行います。たとえば、「explain」というコマンドを利用することでSQLの実行計画を調べることができ、問題点を発見できる場合があります。この分析結果に基づいてチューニングを行なっていきますが、システム全体への影響も考慮しSQLの実行計画やデータ構造を確認しながら慎重に進めていく必要があります。, Indexを設定することで、SQLでも同じ手法でデータにアクセスすることができ、結果的に速度改善が見込めます。, たとえば、ヒント句を使用することでデータベースがどのようにデータを処理するか指示を出すことが可能です。処理の順番が明確であれば適切に利用します。, 問題のある個所を作り変えてしまう手法です。たとえば、「必要な情報を一つのテーブルにまとめ、アクセスするテーブルの数を減少させ、結果的に速度が出る」などの方法があります。, 今回はシステムの速度改善の意義と、SQLチューニングについて取り上げました。速度改善に強いプログラマーは多くの案件で求められる貴重な人材です。普段からスキルを磨いておくと良いでしょう。. * FROM TAB1 a,TAB2 b WHERE a.COL1 = b.COL1, ・テーブル同士をネステッドループで結合したい場合のヒントSELECT /*+USE_NL(a b)*/ a. * FROM TAB1 a,TAB2 b WHERE a.COL1 = b.COL1, ・テーブル同士をハッシュジョインで結合したい場合のヒントSELECT /*+USE_HASH(a b)*/ a. 実行タイミングにより、select *またはselect 1がわずかに遅いケースがありましたが、誤差と言えるでしょう。 メンテナンス性を考えると、他人が「このコード、どういう意味だろう?」と迷うようなSQLは避けた方がよいでしょう。 not existsの使い方まとめ sqlの遅い原因は多岐に渡ります。よくある原因は↓で紹介していますのでぜひ参考にしてください。 投稿させて頂きます。, Select アプリ側で対応するように致しました。, 申し訳ありません。リクエストされたコンテンツは削除されています。すぐに自動的にリダイレクトされます。, SELECTリスト内でのCASEとFORMATによる列値の加工のみで、WHERE句やJOIN句、GROUP BY句などその他には一切変更はないということであれば、純粋にCASEやFORMATのオーバーヘッドが68秒の差になっているということになるかと思います。そうだとすると、改善の方法はないような気がします。結果行数が非常に多いのでしょうか?. * FROM TAB1 a,TAB2 b WHERE a.COL1 = b.COL1, ※もちろん、複数のヒントを同時に利用することもできます。・ORDEREDヒントとUSE_NLを同時に利用した場合SELECT /*+ORDERED USE_NL(a b)*/ a. NULLでない場合、フォーマットして表示したいのですが、 where句を使ってレコードを検索する場合,and,or,inなどを利用すれば複雑な条件の検索が可能です。ただし,テーブルの結合時にテーブル名付きの列名にしなかったり,インデックスを利用できないようなsqlの書き方だと,sqlの検索パフォーマンスが低下する場合があります。 sql 201:実行速度の遅いクエリを見直す10の方法 2019/04/15 09:00 要件把握良し、テーブル確認良し、 テーブル結合も良し 、いつでもクエリを実行させられる準備を整えたあなた。 そんなに記載の仕方が悪いのでしょうか?, CASE WHEN T20.AAAA IS NULL THEN '' ELSE FORMAT(T20.AAAA, 'yyyy/MM/dd') END AS AAAA, とは言え、クエリ結果を受け取るアプリケーションがあるかと思います。アプリケーション側でフォーマットした方が表現力が豊かですし、SQL Server→アプリケーション間の転送データ量も抑えられてパフォーマンスが向上すると思います。, >SELECTリスト内でのCASEとFORMATによる列値の加工のみで、WHERE句やJOIN句、   T20.BBBB ところが、sql文の中でも条件分岐を実現できます。case式を使うのですが、最初に知ったときは感動しました。プログラムのif文とsqlのcase式、使い分けることで全体的にコードをスッキリさせることができます。 case式とは. CASE文を追加しない状態だと12秒程度で結果が返ってきます。, しかし、実際のクエリ + 問題となっているフィールドにCASE文を追加すると sqlを速くするための作業、sql ... が想定通り動作するかどうかと同じくらい重要なことです。時にアプリは、「速度が遅い」という理由で使われなくなってしまいます。 スマホアプリ:挙動が遅いとユーザーにとって大きなストレスになり、利用率の低下やアンインストールに繋がります。 ec 問題となっているフィールドの加工以外、Where句やJoin句、取得している項目等は全て同じです。, 問題の箇所は、SQLクエリで加工するのを止める事にして、 ・作成したインデックスが使われない場合のヒントselect /*+INDEX(a IX_table1_001)*/ * from table1 a where a.col1 = :cond; ・FROM句に書いたテーブルの順番で結合したい場合のヒントSELECT /*+ORDERED*/ a. technology.