この章では、拡張可能索引付けについて説明します。この機能を使用すると、Oracle組込みの索引付けモードに加えて、組み込まれていない索引付けモードを追加実装できます。この章で説明するのは、ドメイン索引を作成する際の決定に役立つ概念上の背景です。ドメイン索引は、拡張可能索引付けフレームワークを使用して作成される索引です。
この章の内容は、次のとおりです。
この項では、索引の作成に使用する用語と方法について説明します。経験豊富なデータベース・アプリケーション開発者は、この説明のほとんどをよく理解しています。ここで説明するのは、他の分野の経験を持つユーザーの参考のためと、用語と方法論についてベースラインを確立するためです。
データベースに含まれるような大量のデータの場合、索引を使用するとデータの検索と取出しが高速かつ効率的になります。データベース内のレコードを参照するかテクニカル・マニュアルの本文を参照するかに関係なく、索引エントリは参照先項目について次の3つのことを示します。
項目の内容(「Mary Leeの従業員情報」や「拡張可能索引付けの定義」など)
項目の場所(「レコード番号1000」または「100ページ」など)
項目の格納方法(「連続するレコード内」または「ページ本文」など)
ほとんどのデータ・セットは複数の異なる方法で索引付けできます。最も有用で効率的なデータ・アクセスを提供するには、通常、適切な索引付け形式を選択することが重要です。これは、すべてのアプリケーションにとって最適な索引付け方法は存在しないためです。
通常、データベース・アプリケーションは問合せでデータを取り出します。問合せでは使用可能なデータのサブセットの選択に索引を使用します。問合せはその表現で使用する演算子に応じて大きく異なる場合があるため、最適なアクセスを提供する索引付け方法も異なります。
サンフランシスコ支社に所属している営業担当を確認するには、等価性をチェックする演算子が必要です。ハッシュ構造では、等価演算子がきわめて効果的に処理されます。
所得がxを超えていてy未満の営業担当を確認するには、範囲をチェックする演算子が必要です。範囲指向の問合せを処理するには、Bツリー構造の方が適しています。
データベースには、医療アプリケーションやマルチメディア・アプリケーションのように、より複雑で特定のタスクに限定された新しいタイプの情報が継続的に取り込まれています。その結果、問合せはますます複雑になり、スキャンする必要のあるデータ量も増大を続けています。Oracleには拡張可能索引付けフレームワークが用意されているため、索引付け方法をデータとアプリケーションにあわせて調整でき、パフォーマンスと使いやすさを向上させることができます。
拡張可能索引付けを使用する場合、アプリケーションでは次の操作を実行します。
索引の構造を定義します。
Oracleデータベース内(索引構成表形式など)またはOracleデータベース外に索引データを格納します。
索引データを管理し、取り出してユーザー問合せの評価に使用します。
したがって、アプリケーションでは索引の構造とセマンティックの内容を制御することになります。データベース・システムはアプリケーションと共同でドメイン索引を作成、維持し、使用します。その結果、索引を作成して作業中のドメイン固有のタスクを実行でき、ユーザーは定義された演算子を使用して通常のような問合せを構成できます。
Oracleの組込み索引付け機能は、様々な状況に適しています。ただし、データが複雑になり、アプリケーションが特定のドメインにあわせて調整されると、他のアプローチを必要とする状況が生じてきます。たとえば、拡張可能索引付けは次のような問題の解決に役立ちます。
特化された索引構造を使用した新規の検索演算子の実装
演算子を定義し、索引構造を使用して特化された検索を実行できます。
構造化されていないデータの索引付け
組込み機能では、LOB
値を含む列の索引付けはできません。
列オブジェクトの属性の索引付け
組込み機能では、列オブジェクトまたはコレクション型の要素の索引付けはできません。
ドメイン固有の操作から導出された値の索引付け
Oracleオブジェクト型は、マップ・ファンクションまたは順序付けファンクションに匹敵します。オブジェクトでマップ・ファンクションが使用される場合は、関係述語の評価に使用するファンクション索引を定義できます。ただし、これが機能するのは有限範囲のパラメータを持つ述語の場合のみで、すべての行のファンクション値を事前計算できる必要があります。また、順序付けファンクションを使用して索引を構成することはできません。
この項では、使用頻度の高い索引構造を紹介し、ドメイン索引の設計者に使用可能な選択肢を示します。
あらゆるニーズを満たす索引構造は存在しませんが、自己均衡型のBツリー索引は大きいデータ・セットの検索パフォーマンスの最適化に最も適しています。各Bツリー・ノードには、複数のキーとポインタが保持されます。特定のBツリーでサポートされている1ノードの最大キー数は、そのツリーの階数です。各ノードは、下位レベルへの階数1個のポインタを持つ可能性があります。たとえば、図7-1に示す階数=2のBツリーにはツリー・ポインタがあり、それぞれ値が第1キーより小さい子ノード、値が第1キーより大きく第2キーより小さい子ノード、値が第2キーより大きい子ノードを指します。つまり、Bツリー・アルゴリズムは、決定ノードごとにキーが1つと子が最大2つしかないバイナリ・ツリー・アルゴリズムよりも少数のノードを通過することで、レコードの検索に必要な読み書き数を最小限に抑えます。ここでは、Knuthバリエーションについて説明します。この場合、索引は2つの部分で構成され、一方はデータへの高速逐次アクセスを提供する順序セットで、他方は順序セットへのダイレクト・アクセスを提供する索引セットです。
通常、Bツリーのノードに同数のデータ値が含まれることはなく、使用されない領域が一定量含まれていますが、Bツリー・アルゴリズムではツリーのバランスが常にとれていることと、リーフ・ノードが同じレベルにあることが保証されます。
ハッシングは、特定のフィールド値に基づいて特定のストアド・レコードへの高速ダイレクト・アクセスを提供します。各レコードの格納位置のアドレスは、そのレコードのなんらかのフィールドのなんらかのファンクションとして計算されます。同じファンクションが挿入と取出しに使用されます。
ハッシングには、論理的な順序付けに関連する場合、レコードの物理的な順序付けが小さいという問題があります。また、ディスク上の未使用領域が大きくなる場合があります。
緯度と経度のような2つのディメンションを持つデータは、2-dツリーと呼ばれるk-dツリーのバリエーションを使用すると効率的に格納し、取り出すことができます。
この構造では、各ノードは情報フィールド、2つの座標、2つの子を指す左リンクと右リンクを持つデータ型です。
この構造は、範囲問合せに適しています。つまり、ユーザーが点(xx, xx)と距離を指定すると、問合せでは原点から指定した距離の範囲内にあるすべての点のセットが戻されます。
2-dツリーは実装が容易です。ただし、k個のノードを含む2-dツリーの高さはkになることがあるため、挿入および問合せが複雑になる可能性があります。
図7-4のように、点quadtreeも2次元空間における点データの表現に使用されますが、2-dツリーではリージョンが2つにわかれているのに対して、この種の構造ではリージョンが4つにわかれています。このノードのレコード・タイプのフィールドは、情報の属性、2つの座標および4つの子を指す4つの方位点(NW、SW、NE、SEなど)で構成されています。
2-dツリーと同様に、点quadtreeは実装が容易です。ただし、k個のノードを含む点quadtreeの高さはkになることがあるため、挿入および問合せが複雑になる可能性があります。それぞれを比較するには、少なくとも2つの座標での比較が必要です。ただし、実際には点quadtreeの方がルートからリーフまでの長さが短くなる傾向があります。
拡張可能索引付けフレームワークは、ドメイン固有の演算子と索引付け方法を定義してOracleサーバーに統合できるSQLベースのインタフェースです。
拡張可能索引付けフレームワークは、次のコンポーネントで構成されています。
索引タイプ: 索引タイプ・スキーマ・オブジェクトでは、アプリケーション固有の索引の定義、メンテナンスおよびスキャン操作を管理するルーチンを指定します。索引タイプにより、表の列またはオブジェクトの属性にユーザー定義索引を設定する方法をOracleサーバーに指示します。
ドメイン索引: 索引タイプを使用して作成されたアプリケーション固有の索引は、アプリケーション固有ドメインのデータに索引付けするため、ドメイン索引と呼ばれます。ドメイン索引は、索引タイプで指定したルーチンにより作成、管理およびアクセスされる索引のインスタンスです。
演算子: 問合せおよびデータ操作文では、空間ドメインにおけるOverlaps
演算子など、アプリケーション固有の演算子を使用できます。ユーザー定義演算子はファンクションにバインドされます。索引を使用して評価することもできます。たとえば、等価演算子はハッシュ索引を使用して評価できます。索引タイプは、定義対象となる演算子の索引ベース実装を提供します。
索引構成表: 索引構成表を使用すると、アプリケーションで表のメタファを使用して複合オブジェクトの索引を定義、作成、メンテナンスおよびアクセスできます。アプリケーションには、索引は各行が索引エントリである表としてモデル化されます。索引構成表では重複する索引エントリが処理されますが、これが複合データ型には重要になる場合があります。
関連項目 索引構成表の詳細は、『Oracle Database管理者ガイド』を参照してください。 |
拡張可能索引付けフレームワークを使用すると、次のことができます。
アプリケーション固有の索引管理ルーチンを、索引タイプ・スキーマ・オブジェクトとしてカプセル化します。
表列にドメイン索引を定義します。
アプリケーション固有の演算子を効率的に処理します。
拡張可能索引付けフレームワークを使用すると、他のOracle索引と同様に動作するドメイン索引を作成できます。ユーザーは、定義された演算子を使用して標準的な問合せを記述します。ドメイン索引の作成、削除、切捨て、変更および検索を行うために、索引タイプの一部として指定したアプリケーション・コードがOracleサーバーにより起動されます。
この項では、拡張可能な索引付けフレームワークについて説明します。例として、Text
索引タイプを使用して新規のテキスト索引付け方法を定義する概略例およびText
索引タイプを使用して、テキスト・データに索引付けおよび操作する概略例を示します。
索引タイプのコンポーネントの作成順序は、索引ベースのファンクション実装を作成するかどうかに応じて異なります。
索引タイプ設計者がText
索引タイプを定義する手順は、次のとおりです。
サポートされている演算子のファンクション実装を定義してコーディングします。
Text
索引タイプでは、演算子Contains
がサポートされます。この演算子はテキスト値とキーを受け入れて、テキストにキーが含まれているかどうかを示す数値を戻します。この演算子のファンクション実装は、次のように定義された標準ファンクションです。
CREATE FUNCTION TextContains(Text IN VARCHAR2, Key IN VARCHAR2) RETURN NUMBER AS BEGIN ....... END TextContains;
新規の演算子を作成してファンクション実装にバインドします。
CREATE OPERATOR Contains BINDING (VARCHAR2, VARCHAR2) RETURN NUMBER USING TextContains;
索引インタフェースODCIIndex
を実装するタイプを定義します。
そのためには、索引定義、索引メンテナンスおよび索引スキャンの各操作用のルーチンを実装する必要があります。Oracleは、次のルーチンをコールします。
ODCIIndexCreate()、ODCIIndexAlter()およびODCIIndexDrop()という索引定義ルーチンをコールして、索引の作成時、変更時、削除時または実表の切捨て時に適切な操作を実行します。
ODCIIndexInsert()、ODCIIndexDelete()およびODCIIndexUpdate()という索引メンテナンス・ルーチンをコールして、表の行の挿入、削除または更新時にテキスト索引をメンテナンスします。
ODCIIndexStart()、ODCIIndexFetch()およびODCIIndexClose()という索引スキャン・ルーチンをコールして、テキスト索引をスキャンし、演算子述語を満たす実表の行を取り出します。
CREATE TYPE TextIndexMethods ( STATIC FUNCTION ODCIIndexCreate(...) ... ); CREATE TYPE BODY TextIndexMethods ( ... );
Text
索引タイプのスキーマ・オブジェクトを作成します。
索引タイプ定義では、新規の索引タイプでサポートされる演算子と、索引インタフェースを実装するタイプを指定します。
CREATE INDEXTYPE TextIndexType FOR Contains(VARCHAR2, VARCHAR2) USING TextIndexMethods WITH SYSTEM MANAGED STORAGE TABLES;
前項に示したText
索引タイプが定義されている場合、ユーザーはテキスト列にテキスト索引を定義し、Contains
演算子を使用してテキスト・データを問い合せることができます。
Employees
表が次の文で定義されているとします。
CREATE TABLE Employees (name VARCHAR2(64), id INTEGER, resume VARCHAR2(2000));
resume
列にテキスト・ドメイン索引を作成するには、次の文を発行します。
CREATE INDEX ResumeIndex ON Employees(resume) INDEXTYPE IS TextIndexType;
resume
列のテキスト・データを問い合せるには、次のような文を発行します。
SELECT * FROM Employees WHERE Contains(resume, 'Oracle') =1;
問合せの実行では、resume
のテキスト索引を使用してContains
条件が評価されます。