Oracle文最適化分析説明第1/2ページ


1.ORACLEの解析器は、FROM子文の表名を右から左の順に処理しますので、FROM子文の最後の表(基礎表driving table)に書いてあります。FROM子文に複数の表が含まれている場合は、記録本数が一番少ない表を基礎表として選択しなければなりません。例えば、表TAB 1 16、384条記録表TAB 2 1条記録選択TAB 2をベーステーブル(最善の方法)select count(*)from tab 1、tab 2実行時間0.96秒でTAB 2をベーステーブル(良くない方法)select count(*)from tab 2として選択し、tab 1実行時間26.09秒2.ORACLEは、この原理に従ってWHEを解析します。表の間の接続は他のWHERE条件の前に書かなければなりません。最大数の記録をフィルタすることができる条件はWHERE子文の末尾に書かなければなりません。例えば:(非効率、実行時間156.3秒)SELECT...FROM EMP E WHERE SAL>50000 AND JOB='MANAGER'AND 25<(SELECT COUNT(*)FROM EMP WHERE MGR=E.EMPNO);高効率、実行時間10.6秒)SELECT…FROM EMP E WHERE 25<(SELECT COUNT(*)FROM EMP WHERE MGR=E.EMPNO)AND SAL>50000 AND JOB=‘MANAGER’;3.SELECT子文の中で「*」を使わないでください。SELECT子文の中にすべてのCOLUMNを並べたい時、動的SQL列を使って「*」を引用するのは便利な方法です。残念なことに、これは非常に非効率的な方法です。実際には、ORACLEでは解析の過程で、*'を順番にすべての列名に変換します。この仕事はデータ辞書を調べて完成します。これはより多くの時間がかかります。4.DECODE関数を使用して処理時間を低減し、DECODE関数を使用して、同じ記録を繰り返しスキャンしたり、同じテーブルに接続したりしないようにすることができます。5.重複記録の最も効率的な削除重複記録方法を削除する(ROWIDを使用しているので)DELETE FROM EMP E WHERE E E.ROWID>(SELECT MIN(X.ROWID)FROM EMP X WHERE X.EMP_NO=E.EMP_NO)6.レコードの数を計算するのは一般的な観点とは逆で、count(*)はcount(1)より少し早いです。もちろんインデックスで検索できるなら、インデックスの列のカウントは一番早いです。例えば、COUNT(EMPNO)7.HAVING子文をWHERE子文に置き換えて、HAVING子文を使わないようにします。HAVINGは全ての記録を検索した後、結果集をフィルタリングします。この処理は並べ替え、合計などの操作が必要です。WHERE子文で記録の数を制限できれば、その方面の出費を減らすことができる。例えば、非効率SELECT REGION、AVG(LOG_)SIZE)FROM LOCATION GROUT BY REGION HAVING REGION REGION!=‘SYDNEY'AND REGION!='PERTH'高効率SELECT REGION,AVG(LOG_SIZE)FROM LOCATION WHERE REGION REGION!=‘SYDNEY'AND REGION!='PERTH'GROUT BY REGION HAVINGの条件は、COUNT()などの集合関数の比較に一般的に使われます。これ以外に、一般的な条件はWHERE子文に書くべきです。8.テーブルのクエリを減らすためには、サブクエリを含むSQL文では、テーブルのクエリを減らすことに特に注意する必要があります。例えば、非効率SELECT TAB_NAME FROM TABLES WHERE TAB_NAME=(SELECT TAB_)NAME FROM TAB_COLUMNS WHERE VERION=604)AND DB_VER=(SELECT DB_VER FROM TAB_COLUMNS WHERE VERION=604)高効率SELECT TAB_NAME FROM TABLES WHERE(TAB_NAME,DB_VER)=(SELECT TAB_NAME,DB_VER)FROM TAB_COLUMNS WHERE VERION=604)9.表の別名ALIASを使用してSQL文に複数の表を接続する場合は、表の別名を使用して、各Columnに別名プレフィックスを付けてください。これにより、解析の時間を短縮し、Columnの曖昧による文法的エラーを低減することができる(Column曖昧とは、SQLにおける異なるテーブルが同じColumn名を持つため、SQL文にこのColumnが現れた場合、SQL解析器はこのColumnの帰属を判断できない)10.INをEXISTSで置換することで、多くの基礎表に基づくクエリーの中で、一つの条件を満たすために、他のテーブルを接続することが多い。この場合、EXISTS(またはNOT EXISTS)を使用すると、クエリの効率が向上します。低効率:SELECT*FROM EMP(ベーステーブル)WHERE EMPNO>0 AND DEPTNO IN(SELECT DEPT NO FROM DEPT WHERE LOC=MELB')高効率:SELECT*FROM EMP(ベーステーブル)WHERE EMPNO>0 AND EXISTS(SELECT'X'FROM DEPT DEPT WHERE DEDEDEDEDEDEDEDEDEEN'DEDEDEDEPT=ANLTS)では、DEPTDEDEDEDEDEDEDEDEDEDEDEDETSでは、DEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDEDETSでは、EXTSの代わります。NOT IN子文は内部の並べ替えと結合を行います。いずれの場合も、NOT_INは最も効果的ではない(サブクエリ中のテーブルに対して全表エルゴードを実行しているから)。NOT INの使用を避けるために、外部接続またはNOT EXISTSに書き換えられます。例えば、SELECT…FROM EMP WHERE DEPT_NO NO NOT IN(SELECT DEPT_NO FROM DEPT WHERE DEPT_CAT='A')効率を上げるために。書き換え:(方法1:高効率)SELECT....FROM EMP A,DEPT B WHERE A.DEPT_NO=B.DEPT(+)AND B.DEPT_NO IS NULL AND B.DEPT_CAT(+)=‘A'(方法2:最高効率)SELECT….FROM EMP E WHERE NOT EXISTS(SELECT'X'FROM DEPT D WHERE D.DEPT_NO=E.DEPT_NO AND DEPT_CAT=‘A’12.表接続でEXISTSを置換する通常は、表接続でEXISTSより効率的にSELECT ENAME FROM EMP E WHERE EXISTS(SELECT‘X’FROM DEPT WHERE DEPT_NO=E.DEPT_NO AND DEPT_CAT=‘A’より効率的)SELECT ENAME FROM DEPT D,EMP E WHERE E E.DEPT_NO=D.DEPT_NO AND DEPT_CAT=‘A’13.DISTINCTをEXISTSで置換し、部門表と従業員表のような一対のテーブル情報を含むクエリーを提出すると、SELECT子文でDISTINCTを使用しないようにします。EXISTで置換することが一般的に考えられます。例えば、効果が低い:SELECT DISTINCT DEPT_。NO,DEPT_N 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.DEPT_NO=D.DEPT_NO)14.索引の列にWHERE子文の計算を使用することを避ける。インデックスの列が関数の一部である場合。最適化器はインデックスを使用せずに全表スキャンを使用する。例:非効率:SELECT...FROM DEPT WHERE SAL*12>25000;高効率:SELECT...FROM DEPT WHERE SAL>25000/12;これは非常に実用的な規則です。必ず覚えてください。
1 2 次のページ 全文を読む