ヘッダーをスキップ
Oracle® Databaseアドバンスト・アプリケーション開発者ガイド
11gリリース2 (11.2)
B56259-09
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

4 データベース・アプリケーションでの索引の使用

索引は表およびクラスタと関連付けられているオプション構造で、これによりSQL問合せをより迅速に実行することができます。このドキュメントで、索引の使用により、索引がない場合よりも高速に情報を検索できるように、Oracle Databaseの索引は、表データへのより高速なアクセス・パスを提供します。索引は問合せをリライトすることなく使用できます。結果は同じですが、より高速に得られます。

この章は、次の情報を補足します。

内容は次のとおりです。

索引の管理のガイドライン

ここでは、索引の管理のガイドラインの概要を説明します。詳細は、『Oracle Database管理者ガイド』を参照してください。

  • 表データの挿入後の索引の作成

  • 正しい表および列の索引付け

  • パフォーマンスのための索引列の順序付け

  • 表当たりの索引数の制限

  • 不要な索引の削除

  • 遅延セグメント作成の理解

  • 索引サイズの見積りと記憶域パラメータの設定

  • 索引ごとの表領域の指定

  • 索引作成の並列化の検討

  • NOLOGGINGを使用する索引の作成の検討

  • 使用禁止または非表示の索引をいつ使用するかの理解

  • 索引の結合または再構築のコストとメリットの検討

  • 制約を使用禁止または削除する前のコストの検討

索引の管理

『Oracle Database管理者ガイド』には、索引の管理に関する情報が含まれています。

  • 索引の作成

  • 索引の変更

  • 索引の使用領域の監視

  • 索引の削除

  • 索引の情報を表示するデータ・ディクショナリ・ビュー

ドメイン索引を使用する場合

ドメイン索引(アプリケーション・ドメイン索引とも呼ばれます)はデータ・カートリッジ(検索エンジンまたは地理情報システムなど)を使用して実装されたアプリケーションに特有のカスタマイズされた索引です。ドメイン索引の詳細は、『Oracle Database概要』を参照してください。


参照:

ドメイン索引をいつ構築するかを決定するための概念的背景については、『Oracle Databaseデータ・カートリッジ開発者ガイド』を参照してください。

ファンクション索引を使用する場合

ファンクション索引は1つまたは複数の列を含む式の値を計算し、それを索引に格納します。索引式は、算術式、あるいはSQL関数、PL/SQLファンクション、パッケージ・ファンクションまたはCコールアウトを含む式のいずれかです。ファンクション索引は、照合キーに基づく言語ソート、SQL文の効率的な言語依存照合、および大/小文字を区別しないソートもサポートします。

ファンクション索引は索引式を使用する問合せのパフォーマンスを向上させます(特に式が計算集中型な場合)。ただし、

  • データベースは索引を使用しない文の処理でも索引式を評価する必要があります。

  • 頻繁に変更する列に対してファンクション索引を使用すると、データベースの維持にコストがかかります。

オプティマイザはファンクション索引をコストベースの最適化のためだけに使用できます。一方、列の索引はコストベースの最適化およびルールベースの最適化の両方のために使用できます。


注意:

  • ファンクション索引にはNULL値を含めることはできません。そのため、列にNULLを含む可能性のある索引式が含まれていないことを確認するか、または索引式にNVL関数を使用してNULLを他の値に置き換えてください(NVLの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。)

  • Oracle Databaseでは降順索引をファンクション索引のように扱います(詳細は、『Oracle Database SQL言語リファレンス』を参照してください)。


内容は次のとおりです。


参照:

  • ファンクション索引のその他の概念は、『Oracle Database概要』を参照してください。

  • ファンクション索引の作成の詳細は、『Oracle Database管理者ガイド』を参照してください。

  • ファンクション索引の言語の詳細は、『Oracle Databaseグローバリゼーション・サポート・ガイド』を参照してください。

  • オプティマイザのファンクション索引の使用方法の詳細は、『Oracle Database概要』を参照してください。

  • パフォーマンスのためのファンクション索引の使用方法の詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。


ファンクション索引のメリット

ファンクション索引には次のようなメリットがあります。

  • ファンクション索引により、データベースが全索引スキャン(『Oracle Database概要』を参照)のかわりに索引範囲スキャン(『Oracle Database概要』を参照)を実行できる機会が増加します。

    WHERE句によって大きな表の15%未満の行が選択された場合、索引範囲スキャンでは通常応答時間が短くなります。式がファンクション索引に実体化されていると、オプティマイザは式で選択される行数をより正確に見積もることができます。

    Oracle Databaseでは索引式が仮想列として表されるので、ANALYZE文(『Oracle Database SQL言語リファレンス』を参照)でヒストグラムを作成できます。

  • ファンクション索引は事前計算を行い、式の値を格納します。

    問合せは式の値を計算するかわりに索引から得ることができます。値を必要とする問合せ、および計算集中型の索引式が増えれば増えるほど、索引によりアプリケーションのパフォーマンスは向上します(例4-1を参照)。

  • ファンクション索引はオブジェクト列またはREF列に対して作成できます。

    索引式はオブジェクト・タイプを戻すメソッドを起動することができます。詳細は、『Oracle Databaseオブジェクト・リレーショナル開発者ガイド』を参照してください(例4-2および『Oracle Database SQL言語リファレンス』の例を参照)。

  • ファンクション索引により、より強力なソートを実行できます。

    索引式には、大/小文字を区別しないソートのためのSQL関数UPPERおよびLOWER(例4-3を参照)、言語ベースのソートのためのSQL関数NLSSORT(例4-4を参照)を含めることができます。

ファンクション索引のデメリット

ファンクション索引には次のようなデメリットがあります。

  • オプティマイザはファンクション索引をコストベースの最適化のためだけに使用できます。ルールベースの最適化には使用できません。

    コストベースの最適化はディクショナリに格納された統計情報を使用します。ファンクション索引の統計情報を収集するには、DBMS_STATS.GATHER_TABLE_STATS(『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照)またはDBMS_STATS.GATHER_SCHEMA_STATS(『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照)のいずれかを起動します。

  • ファンクション索引は、索引自体と索引が定義される表が分析されるまで、使用されません。

    索引と索引が定義される表を分析するにはDBMS_STATS.GATHER_TABLE_STATSまたはDBMS_STATS.GATHER_SCHEMA_STATSを起動します。

  • ファンクション索引は、OR拡張が実行された場合、使用されません。

  • 索引式が呼び出すすべてのスキーマ・レベルまたはパッケージ・レベルPL/SQLファンクションが、DETERMINISTICである(同じ入力に対して常に同じ結果を戻す)ことを確認する必要があります。

    ファンクションはDETERMINISTICとして宣言する必要がありますが、Oracle Databaseはこのアサーションをチェックしないので、ファンクションが実際にDETERMINISTICであることを確認する必要があります。

    DETERMINISTICファンクションのセマンティックを変更し、再コンパイルすると、依存するファンクション索引およびマテリアライズド・ビューを手動で再作成する必要があります。それ以外の場合は、旧バージョンのファンクションの結果がレポートされます。

  • 索引式がファンクション起動の場合、ファンクションの戻り型は制約付きにできません。

    ファンクションの戻り型をNOT NULLで制約できないため、索引を使用する問合せがNULL値をフェッチできないことを保証する必要があります。そうしないと、データベースは全表スキャンを実行します。

  • 索引式は集計関数を呼び出すことができません(『Oracle Database SQL言語リファレンス』を参照)。

  • ビットマップ済のファンクション索引は、降順索引にはできません(『Oracle Database SQL言語リファレンス』を参照)。

  • 索引式のデータ型は、VARCHAR2RAWLONGRAW、または長さが不明のPL/SQLデータ型にはできません。

    つまり、長さが不明な式には索引付けできません。ただし、そのような式の既知の長さのサブストリングには索引付けできます。次に例を示します。

    CREATE OR REPLACE FUNCTION initials (
      name  IN VARCHAR2
    ) RETURN VARCHAR2
      DETERMINISTIC
    IS
    BEGIN
      RETURN('A. J.');
    END;
    /
    
    /* Invoke SUBSTR both when creating index and when referencing
       function in queries. */
     
    CREATE INDEX func_substr_index ON
    EMPLOYEES(SUBSTR(initials(FIRST_NAME),1,10));
     
    SELECT SUBSTR(initials(FIRST_NAME),1,10) FROM EMPLOYEES;
    

参照:

  • ファンクション索引の注意点については、『Oracle Database SQL言語リファレンス』を参照してください。

  • ファンクション索引の制限事項については、『Oracle Database SQL言語リファレンス』を参照してください。

  • 制限事項を含むCREATE FUNCTION文の詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。


ファンクション索引の例

例:


注意:

例4-1および例4-2はコンポジット索引(複数の表の列に対する索引)を使用します。詳細は『Oracle Database概要』を参照してください。

例4-1は列abおよびcのある表を作成し、表に索引を作成し、表に問合せを実行します。索引は式a+b*(c-1)を表す仮想列、列aおよび列bの3つの列に対するコンポジット索引です。問合せはそのWHERE句に索引付けされた式を使用します。そのため、全索引スキャンのかわりに索引範囲スキャンを使用できます。

例4-1 算術式の事前計算用のファンクション索引

索引を作成する表を作成します。

DROP TABLE Fbi_tab;
CREATE TABLE Fbi_tab (
  a INTEGER, 
  b INTEGER, 
  c INTEGER
);

索引を作成します。

CREATE INDEX Idx ON Fbi_tab (a+b*(c-1), a, b);

この問合せは全索引スキャンのかわりに索引範囲スキャンを使用できます。

SELECT a FROM Fbi_tab WHERE a+b*(c-1) < 100;

参照:

高速全索引スキャンの詳細は、『Oracle Database概要』を参照してください。

例4-2では、オブジェクト・タイプReg_objが定義され、そこに都市に関する情報が格納されると仮定します。例では、最初の列にタイプReg_objを含む表、パラメータにタイプReg_objを指定したDETERMINISTICファンクション、ファンクションを起動する2つのファンクション索引を作成します。最初の問合せは最初の索引を使用して赤道から1000マイル以上離れた都市を迅速に検索します。2番目の問合せは2番目の索引(コンポジット索引)を使用して、気温の差が20未満で最高気温が75よりも高い都市を迅速に検索します(表は例が移入されていないので問合せで行は戻りません )。

例4-2 オブジェクト列でのファンクション索引

オブジェクト列を含む表を作成します。

DROP TABLE Weatherdata_tab;
CREATE TABLE Weatherdata_tab (
  Reg_obj INTEGER,
  Maxtemp INTEGER,
  Mintemp INTEGER
);
 

パラメータにタイプReg_objを指定したDETERMINISTICファンクションを作成します。

CREATE OR REPLACE FUNCTION Distance_from_equator (
  Reg_obj IN INTEGER
) RETURN INTEGER
  DETERMINISTIC
IS
BEGIN
  RETURN(3000);
END;
/
 

最初のファンクション索引を作成します。

CREATE INDEX Distance_index
ON Weatherdata_tab (Distance_from_equator (Reg_obj));
 

問合せで索引式を使用します。

SELECT * FROM Weatherdata_tab
WHERE (Distance_from_equator (Reg_Obj)) > '1000';
 

結果:

no rows selected
 

2番目のファンクション(コンポジット)索引を作成します。

CREATE INDEX Compare_index
ON Weatherdata_tab ((Maxtemp - Mintemp) DESC, Maxtemp);
 

問合せで索引式および索引付けされた列を使用します。

SELECT * FROM Weatherdata_tab
WHERE ((Maxtemp - Mintemp) < '20' AND Maxtemp > '75');
 

結果:

no rows selected

例4-3では、EMPLOYEES表でより高速な大/小文字を区別しない検索ができる索引を作成してから、問合せで索引式を使用します。

例4-3 大/小文字を区別しないより高速の検索用のファンクション索引

索引を作成します。

CREATE INDEX emp_lastname ON EMPLOYEES (UPPER(LAST_NAME));

問合せで索引式を使用します。

SELECT first_name, last_name
FROM EMPLOYEES
WHERE UPPER(LAST_NAME) LIKE 'J%S_N';

結果:

FIRST_NAME           LAST_NAME
-------------------- -------------------------
Charles              Johnson
 
1 row selected.

例4-4では、1つの列NAMEを含む表、照合順序GERMANを使用して列をソートするファンクション索引を作成してから、表のすべての列を選択し、NAMEにより順序付けします。問合せは索引を使用できるのでより高速です(問合せはドイツ語セッションで実行され、NLS_SORTGERMANに、NLS_COMPANSIに設定されていると仮定します。そうでない場合、問合せでこれらのグローバリゼーション・サポートのパラメータの値を指定する必要があります)。

例4-4 言語依存ソート用のファンクション索引

索引を作成する表を作成します。

DROP TABLE nls_tab;
CREATE TABLE nls_tab (NAME VARCHAR2(80));

索引を作成します。

CREATE INDEX nls_index
  ON nls_tab (NLSSORT(NAME, 'NLS_SORT = GERMAN'));

表のすべての列を選択し、NAMEによって順序付けします。

SELECT * FROM nls_tab
WHERE NAME IS NOT NULL
ORDER BY NAME;