ハッシュ索引とソート索引は同じ列に定義できます。その後、使用する問合せのタイプに応じて、Oracle Rdbのオプティマイザにより適切な取得方法が選択されます。たとえば、問合せに完全一致での取得が含まれる場合、オプティマイザではハッシュ索引アクセスが使用されます。問合せに範囲取得が含まれる場合、オプティマイザによりソート索引が使用されます。この方法では2つの索引を保持するため追加のオーバーヘッドが発生します。ただし、迅速に取得できるというメリットと、データ変更のたびに索引を2つ更新するというデメリットを考慮する必要があります。
ハッシュ索引およびソート索引の相対的なメリットの詳細は、『Oracle Rdb7 Guide to Database Design and Definition』を参照してください。
SORTED索引を指定する場合、オプションで索引内のノードの特性を制御するNODE SIZE句、PERCENT FILL句およびUSAGE句を指定できます。
UNIQUEを指定すると、SQLによって、その表ですでに索引に重複値が存在しているかどうかがCREATE INDEX文で実行されるときにチェックされます。
リスト内のリテラルの数は、USING句の列の数と同じである必要があります。この句を繰り返して、複数の記憶域に索引のエントリをパーティション化します。リテラルのデータ型は列のデータ型と一致する必要があります。文字の列の場合は、リテラルを一重引用符で囲みます。
複数セグメント・キーおよびSTORE USING...WITH LIMIT句を使用して複数セグメント索引を作成する場合、最初のキーの値がすべて同じ値であれば、最初のキーをその値で制限するよう設定します。これにより、各行の格納先とする記憶域が、2番目のキーの値で決定されるようになります。
- CREATE INDEX文を実行すると、SQLにより物理データベースに索引定義が追加されます。PATHNAME引数を指定してスキーマを宣言している場合、索引定義はリポジトリにも追加されます。
- 索引は、他のユーザーが索引を作成中で、その索引が同じ表にある場合でも、同時に作成可能です。同じ表に同時に索引定義が存在できるようにするには、SET TRANSACTION文のSHARED DATA DEFINITION句を使用します。詳細は、「SET TRANSACTION文」を参照してください。
- 文字長をオクテットで指定している場合(デフォルト)、COMPRESSION句に指定されるサイズもオクテットとなります。
文字長を文字で指定している場合、COMPRESSION句で指定されるサイズも文字となります。- 次のMF_PERSONNELデータベースの例に示すように、DROP INDEX文の後のCREATE INDEX文では、前の文によって使用可能になった領域は再使用されません。結果として、使用されているページ番号を表示すると別の番号が示されます。
SQL> CREATE INDEX INDEX1 ON EMPLOYEES (LAST_NAME) STORE IN RDB$SYSTEM; SQL> COMMIT; SQL> $ RMU/DUMP/LAREA=INDEX1 MF_PERSONNEL SQL> DROP INDEX INDEX1; SQL> COMMIT; SQL> CREATE INDEX INDEX1 ON EMPLOYEES (LAST_NAME) STORE IN RDB$SYSTEM; SQL> COMMIT; SQL> $ RMU/DUMP/LAREA=INDEX1 MF_PERSONNEL
Oracle Rdbでは、表または索引に属しているクランプの再要求は、そのクランプを削除したプロセスがDISCONNECT文またはFINISH文を使用して切断されるまで行われません。
この制限の詳細は、『Oracle Rdb7 Guide to Database Design and Definition』を参照してください。- データベース設計者は、COLLATING SEQUENCE属性で指定されたフィールド、またはデータ型がVARCHARであるフィールドの参照に関する次のオプティマイザ制限を認識しておく必要があります。これらの制限はI/O操作のパフォーマンスに影響を与えます。
索引内のフィールドが定義された照合順番を持つ場合、またはVARCHARフィールドである場合は、オプティマイザでIndex Only Retrievalの方法が無効になります。これら2つの場合の取得方法では、Oracle Rdbで索引ノード内に格納されているデータを返すか、索引ノードのキー・フィールドに基づく比較を実行する必要があり、これによってデータ・レコードに対するI/O操作が削減されます。ただし、これらの属性が使用されている場合、エンコードされた索引から元のユーザー・データを再構築できません。そのため、オプティマイザではかわりにRetrieval by Indexの方法が強制的に使用されます。この方法ではデータ・レコードに対するI/O操作が必要です。
これらの制限は、索引で使用されるフィールドのデータ型の選択に影響する場合があります。たとえば、索引P_INDEXの一部として、データ型CHAR(20)のPRODUCT_IDがあるとします。PRODUCT_IDに対してSTARTING WITHを使用した問合せを指定すると、製品コードの一部を入力できます。続いてユーザーに表示するために、一致するPRODUCT_IDフィールドがフェッチされますが、それ以外のフィールドはフェッチされません。通常であれば、この問合せは索引PRODUCT_ID_IXのみを参照する(Index Only Retrievalの方法を使用する)ように最適化されます。ただし、フィールドがVARCHAR(20)として定義されていた場合、オプティマイザにはPRODUCT_IDをフェッチするためデータ・レコードを参照する必要が生じます。これにより、変換問合せのためにI/O操作がさらに追加されます。したがって、索引の取得に関連するフィールドのデータ型には、VARCHARよりもCHARが適している場合があります。
次の例では、この単純なケースを示します。オプティマイザで行われる方法は、SET FLAGS文を'STRATEGY'とすると表示されます。
SQL> show table PRODUCTS Information for table PRODUCTS Columns for table PRODUCTS: Column Name Data Type Domain ----------- --------- ------ PRODUCT_ID_V VARCHAR(20) PRODUCT_ID_T CHAR(20) . . . Indexes on table PRODUCTS: P_INDEX_T with column PRODUCT_ID_T Duplicates are allowed Type is Sorted Key suffix compression is DISABLED Partition information for index: Implicitly mapped to the default storage area P_INDEX_V with column PRODUCT_ID_V Duplicates are allowed Type is Sorted Key suffix compression is DISABLED Partition information for index: Implicitly mapped to the default storage area . . . SQL> SQL> set flags 'strategy,max_stability'; SQL> SQL> select product_id_t cont> from PRODUCTS cont> where product_id_t starting with 'AAA'; Conjunct Index only retrieval of relation PRODUCTS Index name P_INDEX_T [1:1] 0 rows selected SQL> SQL> select product_id_v cont> from PRODUCTS cont> where product_id_v starting with 'AAA'; Conjunct Get Retrieval by index of relation PRODUCTS Index name P_INDEX_V [1:1] 0 rows selected
注意
ほとんどの問合せでは、データ行(レコード)を参照するための迅速なアクセス方法として索引が使用されます。そのため、通常はデータ・レコードに対するI/O操作が必要です。
- 特定の範囲を超える値を格納する可能性が低い場合、OTHERWISE句は省略できます。そのようにすると記憶域を再構成せずに、最後に新規パーティションを迅速に追加できます。新規パーティションを追加するには、ALTER INDEX文を使用します。次に例を示します。
SQL> ALTER INDEX EMP_HASH_INDEX cont> STORE USING (EMPLOYEE_ID) cont> IN PERSONNEL_1 WITH LIMIT OF ('00399') cont> IN PERSONNEL_2 WITH LIMIT OF ('00699') cont> IN PERSONNEL_3 WITH LIMIT OF ('10000') cont> IN PERSONNEL_4 WITH LIMIT OF ('10399'); SQL>
Oracle Rdbではデータを移動または再構成する必要がない(表内で新規範囲にデータがない)ため、オーバーフロー・パーティションのない索引は迅速に変更できます。
詳細は、『Oracle Rdb7 Guide to Database Design and Definition』および『Oracle Rdb7 Guide to Database Performance and Tuning』を参照してください。- 索引の範囲外の値を挿入しようとすると、次のようなエラーが表示されます。
%RDMS-E-EXCMAPLIMIT, exceeded limit on last partition in storage map for EMPLOYEES
アプリケーションにはこの種のエラーを処理するコードが含まれています。- 同じデータベース表に対してソート索引を効果的にパラレルで作成するには、同時に作成する各索引の索引名は最初の27文字以内で一意である必要があります。一意の名前を指定しない場合は1つのソート索引しか作成されません。これは、各索引の作成が開始される前に同じ名前のロックがリクエストされるためです。
- ランク付きソートBツリー索引の場合、一意索引の作成および複製圧縮の指定はできません。次に例を示します。
SQL> CREATE UNIQUE INDEX test_ndx cont> ON job_history (employee_id) cont> TYPE IS SORTED RANKED cont> DUPLICATES ARE COMPRESSED; %SQL-F-UNIQNODUP, The index TEST_NDX cannot be unique and have a duplicates clause
- CREATE INDEX文では、UNIQUE SORTED索引またはSORTED RANKED索引に何も指定されていない場合、デフォルトの索引ノード・サイズが指定されます。このデフォルトのノード・サイズの値を表示するには、SQLのSHOW INDEX文またはSHOW TABLE文、あるいはRMU Extractコマンドを使用します。
- 索引キーの最大長は255バイトです。Oracle Rdbでは固定長の索引キーが生成されるため、索引の定義時にこの制約がチェックされます。255文字を超えるキーで索引を定義しようとすると、次のようなエラー・メッセージを受け取ります。
SQL> ATTACH 'FILENAME mf_personnel'; SQL> CREATE TABLE TEST_TAB (TEST_COL CHAR (256)); SQL> CREATE INDEX MY_INDEX ON TEST_TAB (TEST_COL); %RDB-E-NO_META_UPDATE, metadata update failed -RDMS-F-INDTOOBIG, requested index is too big
- 列に照合順番が定義されている場合、索引キーが特別にエンコードされて正確な順序(照合)情報が取り込まれます。この特別なエンコーディングには、キーをASCIIでエンコードする場合(照合順番が使用されない場合のデフォルト)よりも多くの領域が必要です。そのため、エンコードされた文字列は、索引内で1文字当たり1バイトの領域を使用する通常の場合よりも多くの領域を使用します。
ノルウェー語を除くすべての照合順番の場合、8文字ごとに約9バイトの領域が必要です。そのため、CHAR(24)の列を格納するには約27バイトが必要になります。ノルウェー語の照合順番の場合は、8文字ごとに約10バイトの領域が必要です。
255バイトの制限に対して索引キーのサイズを計算する際には、文字列のエンコーディングに必要な領域を考慮する必要があります。たとえば、照合順番GERMANを指定して定義されている列が索引で使用されたと仮定します。キーが254バイトにエンコードされるため、この列の長さは最大で225文字に制限されます。
次の例では、ドイツ語の照合順番を指定して定義され、索引に含まれている233文字の列が、長さ255文字未満として定義されている場合にも、255バイトの索引サイズ制限を超過する様子を示します。
SQL> create database cont> filename 'TESTDB.RDB' cont> Collating sequence GERMAN German; SQL> create table EMPLOYEE_INFO ( cont> EMP_NAME CHAR (233)); SQL> create index EMP_NAME_IDX cont> on EMPLOYEE_INFO ( cont> EMP_NAME asc) cont> type is sorted; %RDB-E-NO_META_UPDATE, metadata update failed -RDMS-F-INDTOOBIG, requested index is too big
例1: 単純な表の索引の作成この文では、索引(EMP_EMPLOYEE_ID)に名前が付けられ、索引キーとして機能する列(EMPLOYEE_ID)にも名前が付けられます。
UNIQUE引数が指定されているため、割当て済のID番号をユーザーが格納しようとすると、SQLからエラー・メッセージが返されます。
SQL> CREATE UNIQUE INDEX EMP_EMPLOYEE_ID ON EMPLOYEES cont> (EMPLOYEE_ID);
例2: 降順の索引セグメントを指定した索引の作成
この文では、索引(EMP_EMPLOYEE_ID)に名前が付けられ、降順の索引キーとして機能する列(EMPLOYEE_ID DESCENDING)にも名前が付けられます。
DESCENDINGキーワードが指定されているため、キーが降順でソートされます。DESCENDINGまたはASCENDINGを指定しない場合、SQLによってキーは昇順でソートされます。
SQL> CREATE UNIQUE INDEX EMP_EMPLOYEE_ID ON EMPLOYEES cont> (EMPLOYEE_ID DESCENDING);
例3: 複数セグメント索引の作成
SQL> CREATE INDEX EMP_FULL_NAME ON EMPLOYEES cont> (LAST_NAME, cont> FIRST_NAME, cont> MIDDLE_INITIAL);
この文では、索引EMP_FULL_NAMEで使用される3つの列に名前を付けます。これら3つの列がSQLによって連結され、複数セグメント索引が作成されます。
例4: 圧縮型数値索引の作成
SQL> CREATE INDEX YEAR1_IND ON DEGREES cont> (YEAR_GIVEN ASCENDING MAPPING VALUES 1950 TO 1970);
この文では、DEGREES表のYEAR_GIVEN列に昇順の索引セグメントが作成され、年の値が圧縮されます。
例5: 切捨てテキスト索引の作成
SQL> CREATE INDEX COL_NAME_IND ON COLLEGES cont> (COLLEGE_NAME SIZE IS 20);
この文では、キーとして使用されるCOLLEGE_NAME列のオクテット数が20オクテットを超えないように、圧縮型索引COL_NAME_INDがCOLLEGES表に作成されます。
SQL> ALTER DATABASE FILENAME mf_personnel cont> ADD STORAGE AREA UNIFORM1 PAGE FORMAT IS UNIFORM; SQL> ALTER DATABASE FILENAME mf_personnel cont> ADD STORAGE AREA UNIFORM2 PAGE FORMAT IS UNIFORM; SQL> ATTACH 'FILENAME mf_personnel'; SQL> CREATE UNIQUE INDEX EMP_THRESHOLDS ON EMPLOYEES (EMPLOYEE_ID) cont> TYPE IS SORTED cont> STORE USING (EMPLOYEE_ID) cont> IN RDB$SYSTEM (THRESHOLDS ARE (60,75,90)) cont> WITH LIMIT OF ('00200') cont> IN UNIFORM1 (THRESHOLD IS (65)) cont> WITH LIMIT OF ('00400') cont> OTHERWISE IN UNIFORM2 cont> (THRESHOLD OF (90)); %RDB-W-META_WARN, metadata successfully updated with the reported warning -RDMS-W-IDXCOLEXIST, an index with this column list already exists SQL> -- SQL> SHOW INDEX EMP_THRESHOLDS Indexes on table EMPLOYEES: EMP_THRESHOLDS with column EMPLOYEE_ID No Duplicates allowed Type is Sorted Key suffix compression is DISABLED Node size 430 Store clause: STORE USING (EMPLOYEE_ID) IN RDB$SYSTEM (THRESHOLDS ARE (60,75,90)) WITH LIMIT OF ('00200') IN UNIFORM1 (THRESHOLD IS (65)) WITH LIMIT OF ('00400') OTHERWISE IN UNIFORM2 (THRESHOLD OF (90))
この文では、STORE句を使用して統一ページ形式の複数の記憶域に索引がパーティション化され、しきい値が適用されます。
例7および例8では、データベースMIA_CHAR_SETの表COLOURSが次のように定義されています。
SQL> CREATE TABLE COLOURS cont> (ENGLISH MCS_DOM, cont> FRENCH MCS_DOM, cont> JAPANESE KANJI_DOM, cont> ROMAJI DEC_KANJI_DOM, cont> KATAKANA KATAKANA_DOM, cont> HINDI HINDI_DOM, cont> GREEK GREEK_DOM, cont> ARABIC ARABIC_DOM, cont> RUSSIAN RUSSIAN_DOM);
例7: オクテットの文字長を使用した単純な表の索引の作成(デフォルト)
SQL> SET CHARACTER LENGTH 'OCTETS'; SQL> CREATE INDEX COLOUR_INDEX ON COLOURS (JAPANESE SIZE IS 4) cont> TYPE IS SORTED; SQL> SHOW INDEX COLOUR_INDEX; Indexes on table COLOURS: COLOUR_INDEX with column JAPANESE size of index key is 4 octets Duplicates are allowed Type is Sorted
この文では、4オクテットの圧縮型索引キーが作成されます。
例8: CHARACTERS文字長を使用した索引の作成
SQL> SET CHARACTER LENGTH 'CHARACTERS'; SQL> CREATE INDEX COLOUR_INDEX_2 ON COLOURS (JAPANESE SIZE IS 4) cont> TYPE IS SORTED; SQL> SHOW INDEX COLOUR_INDEX_2; Indexes on table COLOURS: COLOUR_INDEX_2 with column JAPANESE size of index key is 4 characters Duplicates are allowed Type is Sorted
この文では、4文字の圧縮型索引キーが作成されます。
例9: 圧縮を有効にする索引の作成
次の例では、索引を作成して最短ランレングス2の圧縮を有効にする方法を示します。
SQL> CREATE INDEX EMP_NDX ON EMPLOYEES cont> (EMPLOYEE_ID SIZE IS 4) cont> ENABLE COMPRESSION (MINIMUM RUN LENGTH 2); SQL> SHOW INDEX EMP_NDX; Indexes on table EMPLOYEES: EMP_NDX with column EMPLOYEE_ID size of index key is 4 Duplicates are allowed Type is Sorted Compression is ENABLED (Minimum run length 2)
例10: 索引の属性句の使用
SQL> CREATE UNIQUE INDEX JOB_JOB_CODE cont> ON JOBS ( cont> JOB_CODE cont> ASC) cont> TYPE IS SORTED cont> THRESHOLDS ARE (75,83,90) cont> ENABLE COMPRESSION cont> NOLOGGING cont> COMMENT IS 'Used for translation of job codes'; %RDB-W-META_WARN, metadata successfully updated with the reported warning -RDMS-W-DATACMIT, unjournaled changes made; database may not be recoverable SQL> -- SQL returned this message because the NOLOGGING attribute SQL> -- was set.
例11: 索引の作成およびデフォルトのノード・サイズの表示
SQL> -- Create a simple table upon which to define SQL> -- some indexes SQL> SQL> CREATE TABLE TEST_INDEX_TABLE cont> (A CHAR(70), cont> B INTEGER); SQL> SQL> -- Default value is 430 bytes SQL> SQL> CREATE UNIQUE INDEX TEST_INDEX_DEF cont> ON TEST_INDEX_TABLE (A, B) cont> TYPE IS SORTED cont> USAGE UPDATE; SQL> SQL> SHOW TABLE (INDEX) TEST_INDEX_TABLE Information for table TEST_INDEX_TABLE TEST_INDEX_DEF with column A and column B No Duplicates allowed Type is Sorted Compression is DISABLED Node size 430 Percent fill 70
例12: パーティションの名前付け
SQL> -- Alter mf_personnel database to add three slots SQL> -- for storage areas and then add three storage areas. SQL> ALTER DATABASE FILENAME MF_PERSONNEL cont> RESERVE 3 STORAGE AREAS; %RDMS-W-DOFULLBCK, full database backup should be done to ensure future recovery SQL> ALTER DATABASE FILENAME MF_PERSONNEL cont> ADD STORAGE AREA WAGE_LOW; SQL> ALTER DATABASE FILENAME MF_PERSONNEL cont> ADD STORAGE AREA WAGE_MID; SQL> ALTER DATABASE FILENAME MF_PERSONNEL cont> ADD STORAGE AREA WAGE_HIGH; SQL> ATTACH 'FILENAME MF_PERSONNEL.RDB'; SQL> -- Create an index on the JOBS table and name the partitions SQL> CREATE INDEX WAGE_CLASS_IDX ON JOBS (WAGE_CLASS) cont> TYPE IS SORTED cont> STORE USING (WAGE_CLASS) cont> IN WAGE_LOW (PARTITION WAGE_LOW) WITH LIMIT OF ('1') cont> IN WAGE_MID (PARTITION WAGE_MID) WITH LIMIT OF ('3') cont> OTHERWISE IN WAGE_HIGH (PARTITION WAGE_HIGH);
例13: 多数の記憶域にパーティション化された大規模な索引の作成
まず、次のようにデータベース定義を作成します。
SQL> CREATE INDEX ... MAINTENANCE IS ENABLED DEFERRED ...;
次に、各パーティションをパラレル実行で構築するバッチ・ジョブをサブミットします。たとえば、バッチ・ジョブごとに次のようなスクリプトを実行します。
ATTACH 'filename testdatabase'; SET FLAGS 'index_stats'; ALTER INDEX TRANSACTIONS_INDEX BUILD PARTITION PART_1; COMMIT;
最後に、バッチ・ジョブの完了後、データベース管理者はメンテナンス・モードをENABLED IMMEDIATEに変更して、索引を問合せの使用に対してアクティブにする必要があります。ある手順が失敗した場合(考えられる理由は、リソースの制限や失敗したノード)、BUILD ALL PARTITIONS句を追加できます。
SQL> SET FLAGS 'index_stats'; SQL> SET TRANSLATION READ WRITE RESERVING...FOR EXCLUSIVE WRITES; SQL> ALTER INDEX ... BUILD ALL PARTITIONS; SQL> ALTER INDEX ... MAINTENANCE IS ENABLED IMMEDIATE; SQL> COMMIT;
この体系は、CREATE INDEX文を直接発行することと比較して、いくつか利点があります。
- 作成処理はパラレル実行でき、それによりリソースの使用率が向上し(読取りおよびソート対象の行数が減少する)、索引作成にかかる実行時間を短縮できます。
- 処理されるパーティションは、全索引と比較すると小さいため、処理されるデータの量もより少なくなります。これにより、これらのトランザクションに関わる.rujファイルが小さくなり、AIJファイル領域も少なくなります。
- パーティションの構築はそれぞれ別個のトランザクション内で実行され、失敗した手順がある場合に簡単に繰り返すことができるため、CREATE INDEX文全体を繰り返す必要がありません。
- 失敗した手順がある場合、スクリプトに含まれるBUILD ALL PARTITIONS句によってもそれらの手順が繰り返されます。