oracleデータベースsqlの最適化のまとめ
一:whereを使ってhavingを少なく使います。
二枚以上の表を調べる時、記録の少ないものを右に置く。
三:テーブルへのアクセスを減らす。
四:where子が調べている時に、子供の問い合わせは一番前に置いてあります。
五:select文の中でできるだけ*を使わないようにします。
六:できるだけ多くのcomitを使う。
7:Decodeは同じ記録をスキャンしたり、同じテーブルを繰り返し接続することを避けることができます。
八:内部関数によってsql効率も向上します。
9:複数のテーブルを接続する場合、エイリアスを使用して、エイリアスを各フィールドにプレフィックスします。
十:inの代わりにexistsを使います。
十一:not existsはnot inに取って代わる(not in字句は内部の並べ替えと合併を実行して、いかなる情況の下で、not inは最も効果がなくて、サブクエリの中で全表はスキャンしました。not inの使用を避けるために、outer jinsまたはnot existsに書き換えることができる。
十二:表接続はexistsより効率的です。
十三:existsでdistinctを置換する
例:
低い: 高さ:
select distinct dept_ノ、dept_name select dept_ノ、dept_name
from dept d,emp e from dept d
where d.dept_no=e.dept_ノ; where exists(select 1 from emp e where e.dept_no=d.dept_ノ)
14:TKPROFツールを使ってsqlの性能状態を調べます。
15:インデックスで効率を上げる(価格は、インデックスは空間を必要とし、かつ定期的にインデックスを再構築する必要がある:ALTER INDEX<INDEXNAME>REBUILD<TABLESPACENAME);
まず索引の原理を紹介します。次は索引の最適化に対する理解が便利です。
インデックスでrowidを見つけて、ロwidを通じてテーブルにアクセスします。ただし、クエリーの列がindexに含まれている場合は、検索データはインデックスに保存されているので、インデックスにアクセスするだけで、クエリーの要求を満たすことができます。
前提上の要点:16例の中で、LODGING列には唯一の索引があります。MANAGER列には非一意性のインデックスがあります。
16:インデックス範囲クエリ(INDEX RANGE SACEN):
二つの場合に適用されます。
1)範囲のクエリーに基づいて:
SELECT LODGING FROM LODGING WHERE LODGING LIKE'M%
(where字句条件は一連の値を含んでいます。oracleはインデックス範囲の照会方法でLODGING_を調べます。PK)
2)非一意性索引に基づく検索:
SELECT LODGING FROM LODGING WHERE MANAGER='LI'
(このクエリは2ステップに分けられます。LODGING$MANAGERのインデックス範囲は条件に合ったすべてのレコードのrowidを検索して、rowidアクセステーブルを通してLODGING列の値を得ます。インデックスは一意ではない索です。 したがって、データベースはインデックス固有スキャンを実行できません。
where字句では、インデックス列に対応する値の最初の文字がワイルドカードから始まるとインデックスは採用されず、SELECTのように全表スキャンされます。WHERE MANAGER LIKE'%LI'
17:基礎表の選択:
基礎表:最初に訪問したテーブル(通常は全表スキャンでアクセスされます)。
最適化器によってSQL文では基本テーブルの選択が異なります。
CBOを使用すると、最適化器はSQL文の各テーブルの物理的なサイズ、インデックスの状態を確認し、通話料が一番低いパスを選択します。
RBOを使用すれば、すべての接続条件にインデックスが対応しています。この場合、基本表はFROM字句の最後の表です。
例:
SELECT A.NAME、B.MANAGER FROM WOKER A、LODGING B WHERE A.LODGING=B.LODGING=B.LODGING;
LODGING列にインデックスがあり、WORKER表に比較インデックスがないため、WORKER表は照会の基礎表となります。
18:複数の平等な索引:
SQL文の実行経路が複数のテーブルに分布している複数のインデックスを使用することができる場合、oracleは複数のインデックスを使用して実行中にそれらのレコードを統合し、すべてのインデックスに有効なレコードのみを検索します。
oracle選択の実行経路は、唯一のインデックスレベルが非一意のインデックスより高いのは、where字句の索引列と定数が比較的に有効である場合のみです。索引の列と他の表の索引の列を比較すると、このような字句は最適化器の中で非常に低い等級にあります。
表の二つの同じ等級の索引が引用される場合、FROM字句の表の順序によってどれが先に使われるかを決定します。FROM字句の最後の表は索引の優先度が高いです。同じ表の2つの同じレベルの索引が参照される場合、where字句の中で最初に引用された索引が最も高い優先度を持ちます。
例:DEPTNOには、非一意インデックス、EMP_があります。CATには非一意性のインデックスもあります。
SELECT ENAME FROM EMP WHERE DEPT_NO=20 AND EMP_CAT='A'
DEPTNOインデックスは先に検索され、EMP_と同じです。CATインデックスで検索された結果の統合は、次の通りです。
TABLE ACCESS BY ROWID ON EMP
AND_EQUAL
INDEX RANGE SCAN ON DEPT_IDX
INDEX RANGE SCAN ON CAT_IDX
19:式の比較と範囲の比較:
先に例を示します
SELECT ENAME FROM EMP WHERE DEPT_NO>20 AND EMP_CAT='A'
(二つの非一意性索引を前提として、この場合は範囲インデックスは使用されず、EMP_CATインデックスは記録を調べてDEPT_とNO条件を比較する
注意:一意性ですので、範囲を比較する場合、等級は非一意性索引の式より低いです。
二十:強制索引が無効になります。
二つ以上のインデックスが同じレベルを持つ場合、一つのレベルをコマンドoracle最適化器に強制的に使用することができます。いつこのような策略を使いますか?一つのインデックスが一意に近い場合、他のインデックスは多くの重複値を持っています。順序付けとマージはかえって負担になります。このとき、後者はインデックスが無効になるのを防ぐことができます。
(無効な方法:索引の列に計算'+0'または'𞓜''を追加します。
二枚以上の表を調べる時、記録の少ないものを右に置く。
三:テーブルへのアクセスを減らす。
四:where子が調べている時に、子供の問い合わせは一番前に置いてあります。
五:select文の中でできるだけ*を使わないようにします。
六:できるだけ多くのcomitを使う。
7:Decodeは同じ記録をスキャンしたり、同じテーブルを繰り返し接続することを避けることができます。
八:内部関数によってsql効率も向上します。
9:複数のテーブルを接続する場合、エイリアスを使用して、エイリアスを各フィールドにプレフィックスします。
十:inの代わりにexistsを使います。
十一:not existsはnot inに取って代わる(not in字句は内部の並べ替えと合併を実行して、いかなる情況の下で、not inは最も効果がなくて、サブクエリの中で全表はスキャンしました。not inの使用を避けるために、outer jinsまたはnot existsに書き換えることができる。
十二:表接続はexistsより効率的です。
十三:existsでdistinctを置換する
例:
低い: 高さ:
select distinct dept_ノ、dept_name select dept_ノ、dept_name
from dept d,emp e from dept d
where d.dept_no=e.dept_ノ; where exists(select 1 from emp e where e.dept_no=d.dept_ノ)
14:TKPROFツールを使ってsqlの性能状態を調べます。
15:インデックスで効率を上げる(価格は、インデックスは空間を必要とし、かつ定期的にインデックスを再構築する必要がある:ALTER INDEX<INDEXNAME>REBUILD<TABLESPACENAME);
まず索引の原理を紹介します。次は索引の最適化に対する理解が便利です。
インデックスでrowidを見つけて、ロwidを通じてテーブルにアクセスします。ただし、クエリーの列がindexに含まれている場合は、検索データはインデックスに保存されているので、インデックスにアクセスするだけで、クエリーの要求を満たすことができます。
前提上の要点:16例の中で、LODGING列には唯一の索引があります。MANAGER列には非一意性のインデックスがあります。
16:インデックス範囲クエリ(INDEX RANGE SACEN):
二つの場合に適用されます。
1)範囲のクエリーに基づいて:
SELECT LODGING FROM LODGING WHERE LODGING LIKE'M%
(where字句条件は一連の値を含んでいます。oracleはインデックス範囲の照会方法でLODGING_を調べます。PK)
2)非一意性索引に基づく検索:
SELECT LODGING FROM LODGING WHERE MANAGER='LI'
(このクエリは2ステップに分けられます。LODGING$MANAGERのインデックス範囲は条件に合ったすべてのレコードのrowidを検索して、rowidアクセステーブルを通してLODGING列の値を得ます。インデックスは一意ではない索です。 したがって、データベースはインデックス固有スキャンを実行できません。
where字句では、インデックス列に対応する値の最初の文字がワイルドカードから始まるとインデックスは採用されず、SELECTのように全表スキャンされます。WHERE MANAGER LIKE'%LI'
17:基礎表の選択:
基礎表:最初に訪問したテーブル(通常は全表スキャンでアクセスされます)。
最適化器によってSQL文では基本テーブルの選択が異なります。
CBOを使用すると、最適化器はSQL文の各テーブルの物理的なサイズ、インデックスの状態を確認し、通話料が一番低いパスを選択します。
RBOを使用すれば、すべての接続条件にインデックスが対応しています。この場合、基本表はFROM字句の最後の表です。
例:
SELECT A.NAME、B.MANAGER FROM WOKER A、LODGING B WHERE A.LODGING=B.LODGING=B.LODGING;
LODGING列にインデックスがあり、WORKER表に比較インデックスがないため、WORKER表は照会の基礎表となります。
18:複数の平等な索引:
SQL文の実行経路が複数のテーブルに分布している複数のインデックスを使用することができる場合、oracleは複数のインデックスを使用して実行中にそれらのレコードを統合し、すべてのインデックスに有効なレコードのみを検索します。
oracle選択の実行経路は、唯一のインデックスレベルが非一意のインデックスより高いのは、where字句の索引列と定数が比較的に有効である場合のみです。索引の列と他の表の索引の列を比較すると、このような字句は最適化器の中で非常に低い等級にあります。
表の二つの同じ等級の索引が引用される場合、FROM字句の表の順序によってどれが先に使われるかを決定します。FROM字句の最後の表は索引の優先度が高いです。同じ表の2つの同じレベルの索引が参照される場合、where字句の中で最初に引用された索引が最も高い優先度を持ちます。
例:DEPTNOには、非一意インデックス、EMP_があります。CATには非一意性のインデックスもあります。
SELECT ENAME FROM EMP WHERE DEPT_NO=20 AND EMP_CAT='A'
DEPTNOインデックスは先に検索され、EMP_と同じです。CATインデックスで検索された結果の統合は、次の通りです。
TABLE ACCESS BY ROWID ON EMP
AND_EQUAL
INDEX RANGE SCAN ON DEPT_IDX
INDEX RANGE SCAN ON CAT_IDX
19:式の比較と範囲の比較:
先に例を示します
SELECT ENAME FROM EMP WHERE DEPT_NO>20 AND EMP_CAT='A'
(二つの非一意性索引を前提として、この場合は範囲インデックスは使用されず、EMP_CATインデックスは記録を調べてDEPT_とNO条件を比較する
注意:一意性ですので、範囲を比較する場合、等級は非一意性索引の式より低いです。
二十:強制索引が無効になります。
二つ以上のインデックスが同じレベルを持つ場合、一つのレベルをコマンドoracle最適化器に強制的に使用することができます。いつこのような策略を使いますか?一つのインデックスが一意に近い場合、他のインデックスは多くの重複値を持っています。順序付けとマージはかえって負担になります。このとき、後者はインデックスが無効になるのを防ぐことができます。
(無効な方法:索引の列に計算'+0'または'𞓜''を追加します。