データベースのパフォーマンス最適化に関するいくつかのまとめ


(11)HAVING句をWhere句で置換:HAVING句は使用することを避け、HAVINGはすべてのレコードを検索した後にのみ結果セットをフィルタリングする.この処理にはソート,合計などの操作が必要である.WHERE句によって記録の数を制限ことができれば、その分のコストを減らすことができる.(oracleではない)on、where、havingの3つの条件を付けることができる句の中で、onは最初に実行され、whereに次いでhavingは最後に、onはまず条件に合わない記録をフィルタリングしてから統計を行うので、中間演算で処理するデータを減らすことができ、道理で速度が最も速いはずで、whereもhavingより速くなければならない.それはデータをフィルタリングしてからsumを行い、2つのテーブルを結合するときにonを使うからだ.だから1つのテーブルの時、whereとhavingを比較するしかありません.このテーブルクエリ統計の場合、フィルタリングする条件が計算するフィールドに関連していない場合、それらの結果は同じですが、whereはrushmore技術を使用することができますが、havingはできません.速度の面で後者が遅く、計算するフィールドに関連する場合は、計算しない前に、このフィールドの値が不確定であることを示します.前述のワークフローによると、whereの作用時間は計算前に完了します.havingは計算後に機能するので、この場合、両者の結果は異なります.マルチテーブルでクエリーを結合する場合、onはwhereよりも早く機能します.システムはまず,各テーブル間の結合条件に基づいて,複数のテーブルを1つの一時テーブルに合成した後,whereによってフィルタリングし,その後計算し,計算後havingによってフィルタリングする.このように、条件をフィルタリングして正しい役割を果たすには、まずこの条件がいつ機能するべきかを理解してから、そこに置く(12)テーブルに対するクエリーを減らすことを決定する:サブクエリーを含むSQL文の中で、特にテーブルに対するクエリーを減らすことに注意しなければならない.例:
    SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = (SELECT TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)
 
(13)内部関数によりSQL効率を向上する.
複雑なSQLは実行効率を犠牲にすることが多い.上記の運用関数を用いて問題を解決する方法を把握することは,実際の作業において非常に有意義である.
(14)テーブルの別名(Alias):
SQL文に複数のテーブルを接続する場合は、テーブルの別名を使用して各Columnに別名を接頭辞.これにより、解析の時間を短縮することができ、Columnの曖昧さによる文法的誤りを低減することができる.
(15)INの代わりにEXISTS、NOT EXISTSの代わりにNOT IN:
多くのベーステーブルに基づくクエリーでは、ある条件を満たすために、他のテーブルを結合する必要があることが多い.この場合、EXISTS(またはNOT EXISTS)を使用すると、通常、クエリの効率が向上する.サブクエリでは、NOT IN句は内部のソートとマージを実行する.いずれの場合も、NOT INは最も非効率である(サブクエリ内のテーブルに対して全テーブル遍歴を実行するため).NOT INの使用を避けるため、外部接続(Outer Joins)またはNOT EXISTS.に書き換えることができます.
例:
(  )SELECT * FROM  EMP (   )  WHERE  EMPNO > 0  AND  EXISTS (SELECT 1  FROM DEPT  WHERE  DEPT.DEPTNO = EMP.DEPTNO  AND  LOC = ‘MELB')
(  )SELECT  * FROM  EMP (   )  WHERE  EMPNO > 0  AND  DEPTNO IN(SELECT DEPTNO  FROM  DEPT  WHERE  LOC = ‘MELB')
 
(16)「非効率実行」のSQL文を識別する:
現在、SQLの最適化に関する様々なグラフィック化ツールが次々と登場していますが、自分のSQLツールを書いて問題を解決することは常に最善の方法です.
SELECT  EXECUTIONS , DISK_READS, BUFFER_GETS, 
ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, 
ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, 
SQL_TEXT 
FROM  V$SQLAREA 
WHERE  EXECUTIONS>0 
AND  BUFFER_GETS > 0 
AND  (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 
ORDER BY  4 DESC;
 
(17)インデックスによる効率化:
インデックスは、データの検索効率を向上するためのテーブルの概念部分であり、ORACLEは複雑な自己平衡B-tree構造を用いる.通常、インデックスクエリによるデータのスキャンは全テーブルスキャンよりも高速である.ORACLEオプティマイザは、クエリとUpdate文を実行する最適なパスを見つけると、インデックスを使用します.同様に、複数のテーブルを連結する際にインデックスを用いることでも効率を向上することができる.もう1つのインデックスを使用する利点は、プライマリ・キーの一意性の検証を提供することです.LONGまたはLONG RAWデータ型は、ほとんどのカラムをインデックスできます.通常、大規模なテーブルでのインデックスの使用は特に有効である.もちろん、小さなテーブルをスキャンするときにインデックスを使用すると効率が向上することもわかります.インデックスを使用するとクエリーの効率が向上しますが、その代価にも注意する必要があります.インデックスは記憶するスペースが必要であり、定期的なメンテナンスも必要であり、テーブルに記録する増減やインデックス列が変更されるたびにインデックス自体も変更される.これは、各レコードのINSERT,DELETE,UPDATEがこのために4,5回のディスクI/Oを多く払うことを意味する.インデックスには追加のストレージスペースと処理が必要であるため、不要なインデックスはかえってクエリーの反応時間を遅くします.定期的なインデックスの再構築が必要です.「システムメンテナンスクリーンアップ」に「スパムファイルクリーンアップ」があります.
ALTER  INDEX <INDEXNAME> REBUILD <TABLESPACENAME>
 
(18)DISTINCTをEXISTSで置き換える:
部門テーブルや従業員テーブルなどの複数のテーブル情報のペアを含むクエリーを発行する場合、SELECT句でDISTINCTを使用することは避ける.RDBMSコアモジュールは、サブクエリの条件が満たされると、すぐに結果を返すので、EXISTで置き換えることが一般的に考えられる.例:
(非効率):
SELECT  DISTINCT  DEPT_NO,DEPT_NAME  FROM  DEPT D , EMP E 
WHERE  D.DEPT_NO = E.DEPT_NO 
(  ): 
SELECT  DEPT_NO,DEPT_NAME  FROM  DEPT D  WHERE  EXISTS ( SELECT ‘X' 
FROM  EMP E  WHERE E.DEPT_NO = D.DEPT_NO);
 
(19)sql文は大文字である.oracleは常にsql文を解析し、小文字のアルファベットを大文字に変換して実行するので
(20)javaコードではできるだけコネクタ「+」で文字列を接続しないでください.