5 空間データの索引付けおよび問合せ

空間データを使用した問合せのパフォーマンスを向上させるには、空間データのロードが完了した後で、データに対して空間索引を作成する必要があります。

トピック:

関連トピック

5.1 空間索引の作成

効率的にデータにアクセスするには、バルク・ロードまたはトランザクション・ロードによる空間表へのデータのロードが完了した後で、表内の各ジオメトリ列に対して空間索引(空間Rツリー索引)を作成する必要があります。

たとえば、次の文は、すべてのパラメータについてデフォルト値を使用して、territory_idxという空間索引を作成します。

CREATE INDEX territory_idx ON territories (territory_geom)
   INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2;

注意:

INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2の"_V2"の説明は、「システム管理空間索引の使用」を参照してください

空間索引の作成のオプションの詳細は、CREATE INDEX文を参照してください。

索引作成が完了しなかった場合、索引は無効になるため、DROP INDEX <index_name> [FORCE]文で削除する必要があります。

索引付けされる各ジオメトリ列内では、すべてのジオメトリのSDO_SRID値が同じである必要があります。

空間索引は、2次元、3次元または4次元のデータに作成できます。デフォルトの次元数は2ですが、3次元以上のデータの場合は、sdo_indx_dimsパラメータ・キーワードを使用して、索引を作成する次元数を指定できます。(3次元ジオメトリのサポートの詳細は、「3次元の空間オブジェクト」を参照してください。問合せ要素における次元の様々な組合せのサポートについては、「データおよび索引の次元と空間問合せ」を参照してください。)

Oracle Databaseの自動UNDO管理機能またはPGAメモリー管理機能、あるいはその両方を使用しない場合、設定する必要のある初期化パラメータ値の詳細は、「ロールバック・セグメントおよびソート領域サイズ」を参照してください。自動UNDO管理およびPGAメモリー管理の両方は、デフォルトで有効になっており、これらを使用することをお薦めします。

CREATE INDEX文のtablespaceキーワードで指定された表領域(または、tablespaceキーワードが指定されていない場合はデフォルトの表領域)を使用すると、索引データ表、および内部計算用に作成されたいくつかの一時表の両方が保持されます。WORK_TABLESPACEを表領域として指定すると、一時表は作業表領域に格納されます。

1,000,000行を超える大規模な表では、内部ソート操作を実行する場合に一時表領域が必要です。この一時表領域のサイズは、最大値を1GBとして、100×n バイト(n は表の行数)にすることをお薦めします。

空間索引の作成に必要な領域を推定するには、SDO_TUNE.ESTIMATE_RTREE_INDEX_SIZEファンクションを使用します。

この項には次のトピックも含まれます。

トピック:

5.1.1 システム管理空間索引の使用

リリース12.2以降、索引の作成時にINDEXTYPE=MDSYS.SPATIAL_INDEX_V2を指定すると、空間索引をシステム管理できます。空間表または空間索引をパーティション化するかどうかに関係なく、新たに作成するすべての空間索引にこの索引タイプを使用することを強くお薦めします。レガシー空間索引を作成しなおす場合もこの使用をお薦めします。

主な利点は、空間索引の管理が簡単になることです。最も有益なのはパーティション化の場合で、この新しい索引タイプによって、索引のパーティション化管理操作の(すべてではないにしても)ほとんどが必要なくなります。次のようなOracle Database実表パーティション化モデルのほぼすべてがフル・サポートされます。

  • 単一レベル・パーティション化: レンジ、ハッシュ、リスト

  • コンポジット・パーティション化: レンジ-レンジ、レンジ-ハッシュ、レンジ-リスト、リスト-レンジ、リスト-ハッシュ、リスト-リスト、ハッシュ-ハッシュ、ハッシュ-リスト、ハッシュ-レンジ

  • パーティション化の拡張: 時間隔パーティション化(時間隔ベースのコンポジット・パーティションではない)、参照パーティション化、仮想列ベースのパーティション化

以前のINDEXTYPE=MDSYS.SPATIAL_INDEX("_V2"なし)を引き続き使用できます。このタイプの方が索引の作成のパフォーマンスは若干よいです。特に、データ・セットが小さい場合、パーティション化を使用しない場合はよくなります。レガシー空間索引を削除し、以前と完全に同じ形式で再作成する必要がある場合もこの古いタイプを使用します。しかし、空間索引を作成する際、INDEXTYPE=MDSYS.SPATIAL_INDEX_V2を指定することがほとんどでしょう。

次のトピックでINDEXTYPE=MDSYS.SPATIAL_INDEX_V2の使用例を示します。

トピック:

5.1.1.1 空間索引付けの例: 時間隔パーティション化

時間隔パーティション化は、挿入された値が既存のパーティション範囲と一致しない場合にOracle Databaseが実表パーティションを自動的に作成するパーティション化方法です。

次の制限があります。

  • 指定できる実表パーティション化キー列は1列のみで、NUMBERまたはDATE型である必要があります。

  • 時間隔パーティション化は、索引構成表ではサポートされていません。

"currently last seen"列の月に基づいてパーティション化された、DEST_TABLEという名前の実表の次の例について考えてみましょう。

CREATE TABLE dest_table
PARTITION BY RANGE ("CURR_LAST_SEEN_AT")
INTERVAL(NUMTOYMINTERVAL(1, 'MONTH'))
  (PARTITION "YEAR_1999"
     VALUES LESS THAN (TIMESTAMP' 2000-01-01 00:00:00'),
   PARTITION "YEAR_2000"
     VALUES LESS THAN (TIMESTAMP' 2001-01-01 00:00:00'))
PARALLEL 
AS SELECT imo_num,
          last_seen_at           curr_last_seen_at,
          a.geometry.sdo_point.x curr_longitude,
          a.geometry.sdo_point.y curr_latitude,
LAG(last_seen_at) 
  OVER (partition by imo_num ORDER BY last_seen_at) prev_last_seen_at,
LEAD(last_seen_at) 
  OVER (partition by imo_num ORDER BY last_seen_at) next_last_seen_at,
LAG(a.geometry.sdo_point.x) 
  OVER (partition by imo_num ORDER BY last_seen_at) prev_longitude,
LAG(a.geometry.sdo_point.y) 
  OVER (partition by imo_num ORDER BY last_seen_at) prev_latitude,
LEAD(a.geometry.sdo_point.x) 
  OVER (partition by imo_num ORDER BY last_seen_at) next_longitude,
LEAD(a.geometry.sdo_point.y) 
  OVER (partition by imo_num ORDER BY last_seen_at) next_latitude
FROM source_table a;

データがソース表(source_table)から選択されてこのDEST_TABLE表に挿入される際、Oracle DatabaseはCURR_LAST_SEEN_AT列の月で自動的にデータをパーティション化します。対応するパーティションが存在しない場合、Oracle Databaseが新しいパーティションを自動的に作成します。手動の操作は必要ありません。

前述の例では、2つの明示的なパーティションを作成しています。実際のデータを確認するには、データベース・ディクショナリに対して次のような問合せを行って作成されたパーティションを確認します。

SQL> select partition_name, high_value
  2  from user_tab_partitions
  3  where table_name = 'DEST_TABLE'
  4  order by partition_name;

PARTITION_NAME
--------------------------------------------------------------------------------
HIGH_VALUE
--------------------------------------------------------------------------------
SYS_P2881
TIMESTAMP' 2014-08-01 00:00:00'

SYS_P2882
TIMESTAMP' 2014-09-01 00:00:00'

SYS_P2883
TIMESTAMP' 2014-10-01 00:00:00'

SYS_P2884
TIMESTAMP' 2014-11-01 00:00:00'

YEAR_1999
TIMESTAMP' 2000-01-01 00:00:00'

YEAR_2000
TIMESTAMP' 2001-01-01 00:00:00'

6 rows selected.

ここで、空間索引を作成します。次の例では、ファンクション索引を作成します。ファンクションで実表のスカラーの経度と緯度の列が仮想空間ジオメトリに変換され、これが索引のキー値になります。

CREATE OR REPLACE FUNCTION get_geometry(in_longitude NUMBER,
                                        in_latitude  NUMBER)
  return SDO_GEOMETRY DETERMINISTIC PARALLEL_ENABLE IS
BEGIN
  RETURN sdo_geometry(2001,
                      4326,
                      sdo_point_type(in_longitude, in_latitude, NULL),
                      NULL,
                      NULL);
END;
/

INSERT INTO user_sdo_geom_metadata VALUES (
  'DEST_TABLE','SCOTT.GET_GEOMETRY(CURR_LONGITUDE,CURR_LATITUDE)',
   SDO_DIM_ARRAY(SDO_DIM_ELEMENT('Longitude', '-180', '180', '.05'),
                 SDO_DIM_ELEMENT('Latitude',   '-90',  '90', '.05')),
   4326);
COMMIT;

CREATE INDEX geom_idx1
ON dest_table(GET_GEOMETRY(CURR_LONGITUDE, CURR_LATITUDE))
INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2 LOCAL PARALLEL;

空間索引にパーティション化情報が指定されていないことに注意してください。自動的に作成されたパーティションを確認するには、次のような問合せを使用します。

SQL> select partition_name, high_value
  2  from user_ind_partitions
  3  where index_name = 'PRECOMPUTE_GEOM_IDX1'
  4  order by partition_name;

PARTITION_NAME
--------------------------------------------------------------------------------
HIGH_VALUE
--------------------------------------------------------------------------------
SYS_P2921
TIMESTAMP' 2014-08-01 00:00:00'
SYS_P2922
TIMESTAMP' 2014-09-01 00:00:00'
SYS_P2923
TIMESTAMP' 2014-10-01 00:00:00'
SYS_P2924
TIMESTAMP' 2014-11-01 00:00:00'
YEAR_1999
TIMESTAMP' 2000-01-01 00:00:00'
YEAR_2000
TIMESTAMP' 2001-01-01 00:00:00'
6 rows selected.

索引パーティションの数は、CREATE TABLE文で明示的に指定したパーティションと同じ名前の2つのパーティションを含め、実表に作成した数と同じであることに注意してください。ただし、システム生成の索引パーティション名は実表の名前と異なります。

5.1.1.2 空間索引付けの例: 仮想列パーティション化

仮想列は、実表の1つ以上の既存の列に基づいた式です。仮想列はメタデータとして格納されるだけで物理的には領域を消費しませんが、索引付けしたり、オプティマイザ統計とヒストグラムを含むこともできます。仮想列にパーティション化キーを使用した表についてパーティション化がサポートされます

システム管理の空間索引を使用せず、導出された値を使用して表をパーティション化する場合、同じ結果を得るにはDBAが追加の物理列を作成および移入する必要があります。導出された値は、アプリケーションまたは挿入の前に式を評価するトリガーによって移入される必要があります。いずれの場合も、システム管理索引を使用せずにこの目標を達成するには、追加のオーバーヘッドと物理列用の追加のディスク領域が必要になります。

システム管理索引を使用すると、パーティション化キーとして式を使用する機能によって不要なオーバーヘッドを発生させることなく、幅広いビジネス要件を効率的に満たすことができます。これは、既存のデータ列で表をパーティション化できない場合に非常に有用です。

次のREGIONという名前の仮想列を含むACCOUNTSという名前の実表の例について考えてみます。

create table accounts_v
( account_number varchar2(30),
  account_name varchar2(30),
  contact_person varchar2(30),
  region AS (case
             when substr(account_name,1,1) = 'N' then 'NORTH'
             when substr(account_name,1,1) = 'E' then 'EAST'
             when substr(account_name,1,1) = 'S' then 'SOUTH'
             when substr(account_name,1,1) = 'W' then 'WEST'
             end),
  shape mdsys.sdo_geometry
)
partition by list (region)
( partition pN values ('NORTH'),
  partition pE values ('EAST'),
  partition pS values ('SOUTH'),
  partition pW values ('WEST')
);

システム管理のローカル・ドメイン空間索引をSHAPE列に作成します。

insert into user_sdo_geom_metadata
values('ACCOUNTS_V',
       'SHAPE',
       mdsys.sdo_dim_array(
         mdsys.sdo_dim_element('Longitude', -180, 180, 0.05),
         mdsys.sdo_dim_element('Latitude',   -90,  90, 0.05)),
       NULL);
commit;
create index shape_v_idx on accounts_v(shape)
indextype is mdsys.spatial_index_v2 LOCAL;

空間索引パーティション情報が指定されていないことに注意してください。しかし、フル・セットの空間索引パーティションが、ユーザーの介入なしに自動的に作成されます。

レコードが適切なパーティションに配置されているかを確認するには、特定のパーティションに対して問合せを行います。次の問合せは、East地域のアカウントに対するものです。

SQL> select * from accounts_v partition(PE)
  2  order by account_number;

ACCOUNT_NUMBER                 ACCOUNT_NAME
------------------------------ ------------------------------
CONTACT_PERSON                 REGIO
------------------------------ -----
SHAPE(SDO_GTYPE, SDO_SRID, SDO_POINT(X, Y, Z), SDO_ELEM_INFO, SDO_ORDINATES)
--------------------------------------------------------------------------------
8778-5435-5345-5223            E-HORIZON-AUTOMOTIVE
RICK                           EAST
SDO_GEOMETRY(2001, NULL, SDO_POINT_TYPE(2, 2, NULL), NULL, NULL)

1 row selected.

5.1.2 特定のジオメトリ・タイプへのデータの制限

空間索引の作成または再作成時、表内のすべてのジオメトリ、または後で挿入されるすべてのジオメトリを、指定したジオメトリ・タイプにすることができます。このように、データのジオメトリ・タイプを制限するには、CREATE INDEX文またはALTER INDEX REBUILD文のPARAMETERS句でlayer_gtypeキーワードを使用し、「SDO_GTYPE」の「有効なSDO_GTYPE値」表の「ジオメトリ・タイプ」列の値を指定します。次に、レイヤー内の空間データをポリゴンに制限する例を示します。

CREATE INDEX cola_spatial_idx
ON cola_markets(shape)
INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2
PARAMETERS ('layer_gtype=POLYGON');

SDO_GTYPEのジオメトリ・タイプは、データの確認時に階層とみなされます。

  • MULTIフォームには、通常のフォームも含まれます。たとえば、'layer_gtype=MULTIPOINT'を指定すると、レイヤーには、POINTジオメトリおよびMULTIPOINTジオメトリの両方を含めることができます。

  • COLLECTIONを指定すると、レイヤーには、すべてのジオメトリ・タイプを含めることができます。

5.1.3 点に対するコンポジットBツリー空間索引の作成

リリース12.2以降、CREATE INDEX文のPARAMETERS句にcbtree_index=trueおよびlayer_gtype=POINTキーワードを指定して点データにコンポジットBツリー索引を作成できます。次に例を示します。

CREATE INDEX pt_idx on PT_CB(c2) indextype is mdsys.spatial_index_v2 
  PAREMETERS ('layer_gtype=POINT cbtree_index=true');

前述の例では、Rツリー空間索引ではなく、コンポジットBツリー空間索引を作成しています。点データにコンポジットBツリー空間索引を使用すると、次のことが可能です。

  • 空間索引の作成時のパフォーマンスが向上します。

  • 多数のOracleセッションからの同時DMLの実行時、DMLのパフォーマンスが向上します。

ただし、コンポジットBツリー空間問合せのパフォーマンスは非常によいですが、そのデータにRツリー空間索引を使用すると最適な空間問合せのパフォーマンスが得られる場合があります(特に、SPATIAL_VECTOR_ACCELERATIONを推奨値であるTRUEに設定されている場合)。

cbtree_index=trueキーワードは、空間索引の作成(CREATE INDEX文)にのみ使用できます。ALTER INDEXやALTER INDEX REBUILDには使用できません。

コンポジットBツリー空間索引を使用する場合、SDO_JOIN演算子はサポートされません

5.1.4 クロススキーマの索引作成

自分のスキーマ以外にある表に対して、空間索引を作成できます。ユーザーBが、ユーザーAのスキーマにある表T1のGEOMETRY列に空間索引を作成するとします。次の手順に従います。

  1. 権限を持つユーザー(SYSTEMなど)としてデータベースに接続し、次の文を実行します。
    GRANT create table, create sequence to A;
    GRANT create table, create sequence to B;
    
  2. 権限を持つユーザーとして接続するか、またはユーザーAとして接続して(接続をユーザーAに切り替えて)、次の文を実行します。
    GRANT select, index on A.T1 to B;
    
  3. ユーザーBで接続し、次の文を実行します。
    CREATE INDEX t1_spatial_idx on A.T1(geometry)
      INDEXTYPE IS mdsys.spatial_index_v2;

5.1.5 パーティション空間索引の使用

パーティション表にはパーティション空間索引を作成できます。この項では、Oracle Spatial and Graph固有の使用上の考慮事項について説明します。パーティション表およびパーティション索引の詳細は、『Oracle Database VLDBおよびパーティショニング・ガイド』を参照してください。

パーティション空間索引には、次のメリットがあります。

  • パーティション化によってディスクI/O操作が削減されるため、長時間実行問合せの応答時間が短縮されます。

  • I/O操作が各パーティションで同時に実行されるため、同時問合せの応答時間が短縮されます。

  • パーティション・レベルでの作成および再作成操作によって、索引のメンテナンスが容易になります。

    パーティションの索引は、他のパーティションに対する問合せに影響を与えずに再作成できます。また、各ローカル索引の記憶域パラメータは、他のパーティションとは無関係に変更できます。

  • 複数のパーティションの検索にパラレル問合せが実行されます。

    並列度は、USER_INDEXESビューに表示される索引の行のDEGREE列の値(CREATE INDEXALTER INDEXまたはALTER INDEX REBUILD文のPARALLELキーワードの指定値またはデフォルト値)です。

  • マルチプロセッサ・システム環境における問合せ処理が向上します。

    マルチプロセッサ・システム環境では、パーティション化された空間索引を持つ表に対して空間演算子が使用され、問合せで複数のパーティションが検索される場合、複数のプロセッサを使用して問合せを評価できます。使用されるプロセッサの数は、並列度と、問合せの評価に使用されるパーティションの数によって決まります。

空間索引のパーティション化には、次の制限事項が適用されます。

  • 空間表のパーティション・キーは、空間列ではなく、スカラー値である必要があります。

  • 基になる表では、レンジ・パーティション化のみがサポートされています。その他すべての種類のパーティション化は、パーティション空間索引ではサポートされていません。

パーティション空間索引を作成するには、LOCALキーワードを指定する必要があります。(LOCALキーワードを指定しないと、すべての表パーティションのデータに非パーティション空間索引が作成されます。)次の例ではパーティション空間索引を作成します。

CREATE INDEX counties_idx ON counties(geometry)
   INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2 LOCAL;

この例では、索引パーティションの数および配置に、次のデフォルト値を使用します。

  • 索引のパーティション化は、基になる表のパーティション化に基づきます。表パーティションごとに、対応する索引パーティションが作成されます。

  • 各索引パーティションは、デフォルトの表領域に置かれます。

個々のパーティションに対してパラメータを指定する場合は、次の考慮事項が適用されます。

  • 各パーティションには、各パーティションに同じ記憶特性か、またはそれぞれ異なる記憶特性を指定できます。記憶特性が異なる場合は、パラレルI/O (表領域が異なるディスク上にある場合)が使用可能になり、パフォーマンスが向上する場合があります。

  • sdo_indx_dims値には、すべてのパーティションで同じ値を指定する必要があります。

  • 各パーティションに使用されるlayer_gtypeパラメータ値(「特定のジオメトリ・タイプへのデータの制限」を参照)は異なる場合があります。

パーティション化のデフォルト値を上書きするには、次の一般的な形式のCREATE INDEX文を使用します。

CREATE INDEX <indexname> ON <table>(<column>) 
  INDEXTYPE IS MDSYS.SPATIAL_INDEX_V2 
     [PARAMETERS ('<spatial-params>, <storage-params>')] LOCAL 
     [( PARTITION <index_partition> 
        PARAMETERS ('<spatial-params>, <storage-params>') 
     [, PARTITION <index_partition> 
        PARAMETERS ('<spatial-params>, <storage-params>')] 
     )] 

パーティション表で問合せを操作して、1つのパーティションのみに対する問合せを実行できます。次に例を示します。

SELECT * FROM counties PARTITION(p1)
    WHERE ...<some-spatial-predicate>;

複数の問合せを異なるパーティションで同時に操作する場合、選択したパーティションに対する問合せを行うと、問合せが高速化され、スループット全体が向上する場合もあります。

問合せでパーティション空間索引を使用する場合、空間演算子およびファンクションのセマンティック(意味または動作)は、SDO_NN (最も近くにあるもの)の場合を除いて、パーティション索引および非パーティション索引を使用する場合と同じです。SDO_NNの場合、その問合せによって影響されるパーティションごとに、要求した数のジオメトリが戻されます。(詳細は、「空間演算子」SDO_NN演算子の説明を参照してください。)

たとえば、ある地点に最も近い5つのレストランを要求し、空間索引に4つのパーティションがある場合、SDO_NNは最大20 (5×4)のジオメトリを戻します。この場合、最も近い5つのレストランを戻すためにROWNUM疑似列(ここでは、WHERE ROWNUM <=5)を、結果を距離(マイル)でソートするためにORDER BY句を使用する必要があります。例5-1では、パーティション空間索引から最も近い5つのレストランを戻します。

関連項目:

SDO_NN演算子を使用するその他の例については、「SDO_NNの例」を参照してください。

クロススキーマ問合せでは、表にパーティション空間索引がある場合、空間表と、空間表に作成された空間索引の索引表(MDRT_xxx)の両方について、ユーザーにSELECTまたはREAD権限が付与されている必要があります。詳細と例については、SDO_JOIN演算子の「使用上の注意」に記載されている「SDO_JOINのクロススキーマでの使用」を参照してください。

例5-1 パーティション空間索引を使用したSDO_NN問合せ

SELECT * FROM
(
SELECT r.name, r.location, SDO_NN_DISTANCE(1) distance_in_miles
FROM restaurants_part_table r
WHERE SDO_NN(r.location,
      MDSYS.SDO_GEOMETRY(2001,8307,MDSYS.SDO_POINT_TYPE(-110,35,Null),Null,Null),
     'SDO_NUM_RES=5 distance=2  unit=MILE', 1) = 'TRUE'
ORDER BY distance_in_miles
)
WHERE ROWNUM<=5;

トピック:

5.1.5.1 ローカル・パーティション空間索引の作成

ローカル・パーティション空間索引を作成する場合は、PARALLELキーワードを使用するかわりに、この項の手順を使用することをお薦めします。この手順では、(表領域に空きがないなど)なんらかの理由でパーティションの索引作成に失敗した場合に、最初からやり直す必要がなくなります。次の手順に従います。

  1. ローカル空間索引を作成し、UNUSABLEキーワードを指定します。次に例を示します。
    CREATE INDEX sp_idx ON my_table (location) 
      INDEXTYPE IS mdsys.spatial_index_v2 
      PARAMETERS ('tablespace=tb_name work_tablespace=work_tb_name') 
      LOCAL UNUSABLE;
    

    この文の実行は短時間で行われ、索引に関連付けられたメータデータが作成されます。

  2. ALTER INDEX REBUILD文を使用したスクリプトを作成しますが、PARALLELキーワードは指定しません。たとえば、パーティションが100個、プロセッサが10個ある場合は、次のようにALTER INDEX文を10個使用したスクリプトを10個作成します。
    ALTER INDEX sp_idx REBUILD PARTITION ip1;
    ALTER INDEX sp_idx REBUILD PARTITION ip2;
    . . .
    ALTER INDEX sp_idx REBUILD PARTITION ip10;
    
  3. すべてのスクリプトを同時に実行します。これにより、各プロセッサが単一パーティションの索引に対して機能する一方で、すべてのプロセッサではその一連のALTER INDEX文による動作が進められます。

ALTER INDEX文のいずれかが失敗しても、操作が正常に完了したパーティションを再作成する必要はありません。

5.1.6 索引を含むパーティションの交換

ALTER TABLE文でEXCHANGE PARTITION ... INCLUDING INDEXES句を使用すると、空間表パーティションおよびその索引パーティションを対応する表およびその索引と交換できます。パーティションの交換については、『Oracle Database SQL言語リファレンス』のALTER TABLE文の説明を参照してください。

この機能を使用すると、次のような様々な状況でより効率的に操作を実行できます。

  • データをパーティション表に挿入し、索引作成のコストを回避する場合。

  • パーティション索引を管理および作成する場合。たとえば、データを複数表に分割できます。各表の索引を1つずつ作成して、索引作成中に必要なメモリーおよび表領域リソースを最小化できます。または、索引を複数のセッションでパラレルで作成することもできます。その後、表を(索引とともに)元のデータ表のパーティションと交換できます。

  • オフライン挿入操作を管理する場合。新しいデータを一時表に格納し、定期的に新しいパーティションと交換できます(履歴データを含むデータベース内など)。

索引を含むパーティションを空間データおよびその索引と交換するには、2つの空間索引(1つはパーティションの索引、もう1つは表の索引)が同じ次元数(sdo_indx_dims値)である必要があります。2つの索引が同じ次元数でない場合は、エラーが発生します。表データは交換されますが、索引は交換されず、変換に失敗したことが示されます。索引を使用するには、その索引を再作成する必要があります。

5.1.7 空間索引および空間データのエクスポートとインポートに関する考慮事項

エクスポート・ユーティリティを使用して空間データを含む表をエクスポートする場合、その処理の動作は、空間データが空間索引付けされているかどうかによって異なります。

  • 空間データが空間索引付けされていない場合、表データはエクスポートされます。ただし、適切な情報でターゲット・システムのUSER_SDO_GEOM_METADATAビューを更新する必要があります。

  • 空間データが空間索引付けされている場合は、表データがエクスポートされ、ターゲット・システムのUSER_SDO_GEOM_METADATAビューに適切な情報が挿入され、ターゲット・システムに空間索引が作成されます。ただし、USER_SDO_GEOM_METADATAビューへの挿入が失敗した場合(たとえば、その空間レイヤーのUSER_SDO_GEOM_METADATAエントリがすでに存在する場合)、空間索引は作成されません。

インポート・ユーティリティを使用して、空間索引付けされたデータをインポートする場合は、次の考慮事項が適用されます。

  • エクスポートするデータの索引がTABLESPACE句を使用して作成された場合、その指定表領域がインポート時にデータベースに存在しないと、索引は作成されません。(これはOracleの他の索引とは異なる動作です。他の索引では、元の索引に指定された表領域がインポート時に存在しない場合、索引はユーザーのデフォルトの表領域に作成されます。)

  • 権限を持つデータベース・ユーザーがインポート操作を実行することが必要な場合にFROMUSERおよびTOUSER書式を使用するときは、インポート操作を実行する前に、次の例に示すように、CREATE TABLEおよびCREATE SEQUENCE権限をTOUSERユーザーに付与しておく必要があります(プロンプトが表示されたらSYSTEMアカウントのパスワードを入力します)。

    sqlplus system
    SQL> grant CREATE TABLE, CREATE SEQUENCE to CHRIS;
    SQL> exit;
    imp system file=spatl_data.dmp fromuser=SCOTT touser=CHRIS
    

エクスポート・ユーティリティおよびインポート・ユーティリティの詳細は、『Oracle Databaseユーティリティ』を参照してください。

5.1.8 分散トランザクションとOracle XAトランザクションでのRツリー空間索引の未サポート

Rツリー空間索引の使用は、分散トランザクションやOracle XAトランザクションではサポートされません。分散トランザクションをRツリー空間索引と組み合せて使用すると、次の例外で現在のトランザクションが終了し、ロールバックされます。

ORA-13078: "cannot commit a distributed transaction involving spatial index"

たとえば、分散トランザクションまたはOracle XAトランザクション内でRツリー空間索引を含む表に対してDML操作を使用しないでください。このコンテキストでのRツリー空間索引の使用は公式にはサポートされていません。

注意:

点データに対するコンポジットBツリー索引(「点に対するコンポジットBツリー空間索引の作成」を参照)は、分散トランザクションおよびOracle XAトランザクションでサポートされています

分散トランザクションの詳細は、『Oracle Database管理者ガイド』を参照してください。

5.1.9 空間索引統計へのアクセスの有効化

Oracle Databaseのオプティマイザは、データベースおよびそのオブジェクトに関する詳細を表す統計を収集します。統計は、オプティマイザが各SQL文に対して最適な実行計画を選択するために不可欠のものです。オプティマイザ統計の詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

DBMS_STATS.GATHER_INDEX_STATSDBMS_STATS.GATHER_SCHEMA_STATSなどのプロシージャを使用して空間索引関連の索引統計を収集できるようにするには、統計収集を実行するデータベース・ユーザー全員にCREATE TABLE権限が付与されている必要があります。

異なるスキーマ(ユーザー)について空間ドメイン索引でANALYZE INDEXを実行する場合、ANALYZE操作を実行するユーザーに次の権限が必要です。

  • 欠落している一時表を作成する場合、CREATE ANY TABLE

  • 既存の一時表を切捨てまたは削除する場合、DROP ANY TABLE

統計が正常に収集された場合は、統計収集対象の索引ごとに、MDXT_%objID%という形式の名前で表が作成されます。このような表のそれぞれに格納される空間統計データは、デフォルトでは512行です。

5.1.10 ロールバック・セグメントおよびソート領域サイズ

この項は、ユーザー(データベース管理者)がOracle Databaseの自動UNDO管理機能またはPGAメモリー管理機能のいずれかを使用していないか、あるいはこの両方を使用していない場合にのみ適用されます。自動メモリー管理およびPGAメモリー管理は、デフォルトで有効になっており、これらを使用することをお薦めします。これらの機能の詳細は、次を参照してください。

自動UNDO管理を使用していない場合、ロールバック・セグメントの大きさが十分でないと、空間索引の作成は失敗します。ロールバック・セグメントは、100×nバイト(nは索引付けされるデータの行数)である必要があります。たとえば、1,000,000行ある表の場合、ロールバック・セグメントのサイズは100,000,000バイトである必要があります。

十分なロールバック・セグメントを確保する場合、または空間索引の作成時にロールバック・セグメントを拡張できないというエラーが発生した場合は、ユーザー(またはDBA)が、ロールバック・セグメントのサイズおよび構造を再確認します。適切なサイズのパブリック・ロールバック・セグメントを作成し、そのロールバック・セグメントをオンラインにします。また、大きな空間索引の操作中は、不適切で小さなロールバック・セグメントがすべてオフラインになっていることを確認してください。

PGAメモリー管理機能を使用していない場合、データベース・パラメータSORT_AREA_SIZEは、索引作成に必要な時間に影響します。SORT_AREA_SIZEの値は、ソート操作で使用するメモリーの最大バイト数です。最適値はデータベースのサイズによって異なりますが、空間索引を作成する場合は1,000,000バイト以上にすることをお薦めします。SORT_AREA_SIZEの値を変更する場合は、ALTER SESSION文を使用します。次の文は、値を20,000,000バイトに変更します。

ALTER SESSION SET SORT_AREA_SIZE = 20000000;

5.2 空間データの問合せ

空間レイヤーの構造を使用して、空間問合せと空間結合が解決されます。

Spatial and Graphでは、「問合せモデル」で説明したとおり、空間問合せおよび空間結合を解決するために、1次フィルタ処理と2次フィルタ処理を含む2層問合せモデルを使用します。2層とは、問合せの解決のために2種類の別々の処理が実行されることを指します。両方の処理が実行されると、完全一致の結果セットが戻されます。

問合せ内の空間表に空間索引が定義されている場合、その表の名前にデータベース・リンク(dblink)名を追加することはできません。

この項には次のトピックも含まれます。

トピック:

5.2.1 空間問合せ

空間Rツリー索引では、各ジオメトリが最小境界矩形(MBR)で表現されます(「Rツリー索引」を参照)。図5-1のような、複数のオブジェクトを含むレイヤーについて考えてみます。各オブジェクトには、ジオメトリ名が付いており(線ストリングにはgeom_1、4面のポリゴンにはgeom_2、三角形ポリゴンにはgeom_3、楕円にはgeom_4)、各オブジェクトのMBRは破線で表されています。

図5-1 ジオメトリとMBR

図5-1の説明が続きます
図5-1「ジオメトリとMBR」の説明

一般的な空間問合せでは、問合せウィンドウ(定義された範囲またはウィンドウ)の内部に位置するすべてのオブジェクトが要求されます。動的問合せウィンドウとは、データベース内には定義されず、使用前に定義が必要な矩形領域を指します。図5-2に、図5-1と同じジオメトリに、太い点線のボックスで表されている問合せウィンドウを追加したものを示します。

図5-2 問合せウィンドウを追加したレイヤー

図5-2の説明が続きます
図5-2「問合せウィンドウを追加したレイヤー」の説明

図5-2で、問合せウィンドウは、ジオメトリgeom_1およびgeom_2の一部と、geom_3のMBRの一部を覆っていますが、実際のgeom_3ジオメトリは覆っていません。問合せウィンドウは、geom_4ジオメトリまたはそのMBRを覆っていません。

トピック:

5.2.1.1 1次フィルタ用の演算子

SDO_FILTER演算子(「空間演算子」を参照)は、Spatial and Graphの問合せ処理モデルに含まれる2段階の処理のうち、1次フィルタ部分を実装します。1次フィルタは、候補オブジェクトの組合せの集合が相互作用するかどうかを判断するためにのみ索引データを使用します。具体的には、1次フィルタは、候補オブジェクト自体が相互作用するかどうかではなく、候補オブジェクトのMBRが相互作用するかどうかを確認します。SDO_FILTER演算子の構文は、次のとおりです。

SDO_FILTER(geometry1 SDO_GEOMETRY, geometry2 SDO_GEOMETRY, param VARCHAR2)

前の構文では:

  • geometry1は、表のSDO_GEOMETRY型の列です。この列は、空間索引付けされている必要があります。

  • geometry2は、SDO_GEOMETRY型のオブジェクトです。このオブジェクトは、表から取り出される場合とそうでない場合があります。表から取り出される場合は、空間索引付けされている場合とされていない場合があります。

  • paramは、VARCHAR2型のオプションの文字列です。min_resolutionキーワードとmax_resolutionキーワードのいずれか、または両方を指定できます。

次の例では、1次フィルタ処理のみを実行します(2次フィルタ処理は実行しません)。この例では、図5-2に示すジオメトリのうち、MBRが問合せウィンドウと交差するすべてのジオメトリが戻されます。次の例の結果は、ジオメトリgeom_1、geom_2、geom_3です。

例5-2では、問合せウィンドウを表に挿入せずに1次フィルタ処理を実行します。そのウィンドウはメモリー内で索引付けされるため、パフォーマンスが大幅に向上します。

例5-2 一時問合せウィンドウを使用した1次フィルタ

SELECT A.Feature_ID FROM TARGET A
 WHERE sdo_filter(A.shape, SDO_geometry(2003,NULL,NULL,
                                       SDO_elem_info_array(1,1003,3),
                                       SDO_ordinate_array(x1,y1, x2,y2))
                           ) = 'TRUE';	

例5-2では、(x1,y1)および(x2,y2)は、問合せウィンドウの左下および右上の角です。

例5-3では、問合せ自体にウィンドウ・パラメータを指定するのではなく、SDO_GEOMETRY型の一時的なインスタンスが、問合せウィンドウ用に構成されます。

例5-3 問合せウィンドウの一時的なインスタンスを使用した1次フィルタ

SELECT A.Feature_ID FROM TARGET A
 WHERE sdo_filter(A.shape, :theWindow) = 'TRUE';	

例5-4では、問合せウィンドウが、WINS_1というIDを持つ表WINDOWSに挿入されたとします。

例5-4 ストアド問合せウィンドウを使用した1次フィルタ

SELECT A.Feature_ID FROM TARGET A, WINDOWS B
 WHERE B.ID = 'WINS_1' AND 
  sdo_filter(A.shape, B.shape) = 'TRUE';	

B.SHAPE列が空間索引付けされていない場合、SDO_FILTER演算子は、問合せウィンドウをメモリー内で索引付けするため、高いパフォーマンスを実現します。

5.2.1.2 1次フィルタおよび2次フィルタ用の演算子

SDO_RELATE演算子(「空間演算子」を参照)は、1次フィルタおよび2次フィルタの両方の処理を、問合せ処理時に実行します。2次フィルタは、実際に相互作用する候補オブジェクトのみが選択されていることを確認します。この演算子は、2次元のデータに空間索引が作成されている場合にのみ使用できます。SDO_RELATE演算子の構文は次のとおりです。

SDO_RELATE(geometry1  SDO_GEOMETRY,
           geometry2  SDO_GEOMETRY,
           param      VARCHAR2)

前の構文では:

  • geometry1は、表のSDO_GEOMETRY型の列です。この列は、空間索引付けされている必要があります。

  • geometry2は、SDO_GEOMETRY型のオブジェクトです。このオブジェクトは、表から取り出される場合とそうでない場合があります。表から取り出される場合は、空間索引付けされている場合とされていない場合があります。

  • paramは、引用符で囲まれた文字列で、maskキーワードと有効なマスク値を持ちます。オプションで、min_resolutionキーワードまたはmax_resolutionキーワード(あるいはその両方)も設定されます。詳細は、「空間演算子」SDO_RELATE演算子の説明を参照してください。

次の例では、1次フィルタおよび2次フィルタの両方の処理を実行します。この例では、図5-2に示すジオメトリのうち、問合せウィンドウ内に位置する、または部分的に重なるすべてのジオメトリが戻されます。これらの例の結果は、オブジェクトgeom_1およびgeom_2です。

例5-5では、問合せウィンドウを表に挿入せずに、1次フィルタおよび2次フィルタの両方の処理を実行します。そのウィンドウはメモリー内で索引付けされるため、パフォーマンスが大幅に向上します。

例5-5 一時問合せウィンドウを使用した2次フィルタ

SELECT A.Feature_ID FROM TARGET A
   WHERE sdo_relate(A.shape, SDO_geometry(2003,NULL,NULL,
                                       SDO_elem_info_array(1,1003,3),
                                      SDO_ordinate_array(x1,y1, x2,y2)),
                        'mask=anyinteract') = 'TRUE';

例5-5では、(x1,y1)および(x2,y2)は、問合せウィンドウの左下および右上の角です。

例5-6では、問合せウィンドウが、WINS_1というID値を持つ表WINDOWSに挿入されたとします。

例5-6 ストアド問合せウィンドウを使用した2次フィルタ

SELECT A.Feature_ID FROM TARGET A, WINDOWS B
 WHERE B.ID = 'WINS_1' AND 
        sdo_relate(A.shape, B.shape,
          'mask=anyinteract') = 'TRUE';	

B.SHAPE列が空間索引付けされていない場合、SDO_RELATE演算子は、問合せウィンドウをメモリー内で索引付けするため、高いパフォーマンスを実現します。

5.2.1.3 WITHIN_DISTANCE演算子

SDO_WITHIN_DISTANCE演算子(「空間演算子」を参照)は、参照オブジェクトからn距離単位内に、表内のオブジェクトの集合があるかどうかを判断するために使用されます。この演算子は、2次元のデータに空間索引が作成されている場合にのみ使用できます。参照オブジェクトは、SDO_GEOMETRYの一時的または永続的なインスタンス(一時問合せウィンドウやデータベースに格納された永続的ジオメトリなど)です。演算子の構文は次のとおりです。

SDO_WITHIN_DISTANCE(geometry1  SDO_GEOMETRY, 
                    aGeom      SDO_GEOMETRY,
                    params     VARCHAR2);

前の構文では:

  • geometry1は、表のSDO_GEOMETRY型の列です。この列は、空間索引付けされている必要があります。

  • aGeomは、SDO_GEOMETRY型のインスタンスです。

  • paramsは、演算子の動作を判断する、キーワードの値のペアを引用符で囲んだ文字列です。パラメータ・リストの詳細は、「空間演算子」SDO_WITHIN_DISTANCE演算子を参照してください。

次の例では、問合せウィンドウから1.35距離単位内にあるオブジェクトを選択します。

SELECT A.Feature_ID
  FROM TARGET A
  WHERE SDO_WITHIN_DISTANCE( A.shape, :theWindow, 'distance=1.35') = 'TRUE';

距離単位は、使用しているジオメトリ座標系に基づきます。測地座標系を使用する場合、単位はmです。座標系を使用しない場合、単位は格納されたデータの場合と同じです。

SDO_WITHIN_DISTANCE演算子は、空間結合の実行に適していません。「海岸線から10距離単位以内にあるすべての駐車場(parks)を検索」のような問合せは、COASTLINES表およびPARKS表の索引ベースの空間結合として処理されません。かわりに、それぞれのCOASTLINESインスタンスが順番にPARKS表に対してバッファ、索引付けおよび評価される参照オブジェクトになるネステッド・ループ問合せとして処理されます。このようにSDO_WITHIN_DISTANCE演算子は、COASTLINES表にn 行がある場合にn 回実行されます。

非測地データの場合、レイヤーのすべてのジオメトリのバッファリングが必要な空間結合を実行する、効率的な方法があります。この方法では、SDO_WITHIN_DISTANCE演算子は使用しません。まず、新しい表COSINE_BUFSを次のように作成します。

CREATE TABLE cosine_bufs UNRECOVERABLE AS
   SELECT SDO_BUFFER (A.SHAPE, B.DIMINFO, 1.35)
     FROM COSINE A, USER_SDO_GEOM_METADATA B
     WHERE TABLE_NAME='COSINES' AND COLUMN_NAME='SHAPE';

次に、COSINE_BUFSのSHAPE列に空間索引を作成します。これによって、次の問合せを実行できます。

SELECT /*+ ordered */ a.gid, b.gid 
  FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 
                      'COSINE_BUFS', 'SHAPE',
                      'mask=ANYINTERACT')) c,
       parks a, 
       cosine_bufs b
  WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;
5.2.1.4 Nearest Neighbor演算子

SDO_NN演算子(「空間演算子」を参照)は、最も近くにあるジオメトリを識別するために使用します。この演算子は、2次元のデータに空間索引が作成されている場合にのみ使用できます。演算子の構文は次のとおりです。

SDO_NN(geometry1  SDO_GEOMETRY, 
       geometry2  SDO_GEOMETRY,
       param      VARCHAR2
       [, number  NUMBER]);

前の構文では:

  • geometry1は、表のSDO_GEOMETRY型の列です。この列は、空間索引付けされている必要があります。

  • geometry2は、SDO_GEOMETRY型のインスタンスです。

  • paramは、キーワードと値のペアを引用符で囲んだ文字列で、近くにあるジオメトリをいくつ戻すかといった、演算子の動作を決定できます。このパラメータの詳細は、「空間演算子」SDO_NN演算子を参照してください。

  • numberは、SDO_NN_DISTANCEのコールで使用される数と同じ数です。これは、SDO_NN_DISTANCE補助演算子がSDO_NNのコールに含まれている場合にのみ使用します。このパラメータの詳細は、「空間演算子」SDO_NN演算子を参照してください。

次の例では、COLA_MARKETS表のSHAPE列から、指定した点(10,7)に最も近い2つのオブジェクトを検索します。(SELECT文のオプティマイザ・ヒントの使用方法は、「空間演算子」SDO_NN演算子の「使用上の注意」を参照してください。)

SELECT /*+ INDEX(cola_markets cola_spatial_idx) */
 c.mkt_id, c.name  FROM cola_markets c  WHERE SDO_NN(c.shape,
   SDO_geometry(2001, NULL, SDO_point_type(10,7,NULL), NULL,
   NULL),  'sdo_num_res=2') = 'TRUE'; 
5.2.1.5 空間ファンクション

Spatial and Graphでは、ジオメトリ間の関係の判断、単一のジオメトリに関する情報の検索、ジオメトリの変更および結合を行うためのファンクションも提供されます。これらのすべてのファンクションでは、2次元のソース・データが考慮されます。これらのファンクションの出力値がジオメトリの場合、結果のジオメトリの次元は入力ジオメトリと同じになりますが、最初の2次元のみに操作の結果が正確に反映されます。

5.2.2 空間結合

空間結合は、条件で空間演算子を使用することを除いて、通常の結合と同じです。Spatial and Graphでは、あるレイヤーのすべてのジオメトリと別のレイヤーのすべてのジオメトリを比較する場合、空間結合に領域が必要です。これは、単一のジオメトリとレイヤーのすべてのジオメトリを比較する問合せウィンドウとは異なります。

空間結合を使用すると、「国立公園を横切る高速道路はどれか?」のような質問に対する回答を得ることができます。

次の表構造で、この例の結合の実行方法を示します。

PARKS(    GID VARCHAR2(32), SHAPE SDO_GEOMETRY)
HIGHWAYS( GID VARCHAR2(32), SHAPE SDO_GEOMETRY) 

空間結合を実行するには、SDO_JOIN演算子を使用します(「空間演算子」を参照)。次の空間結合問合せでは、高速道路と公園が交差する場所の高速道路と公園のGID列の値を表示するために、1次フィルタ処理のみ('mask=FILTER')が実行されるため、次のようなおおまかな結果のみが戻されます。

SELECT /*+ ordered */ a.gid, b.gid 
  FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 
                      'HIGHWAYS', 'SHAPE',
                      'mask=FILTER')) c,
       parks a, 
       highways b
  WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;

注意:

コンポジットBツリー空間索引を使用する場合、SDO_JOIN演算子はサポートされません。

次の空間結合問合せは、前述の例と同じ情報を要求しますが、1次と2次の両方のフィルタ処理('mask=ANYINTERACT')を実行するため、正確な結果を戻します。

SELECT /*+ ordered */ a.gid, b.gid 
  FROM TABLE(SDO_JOIN('PARKS', 'SHAPE', 
                      'HIGHWAYS', 'SHAPE',
                      'mask=ANYINTERACT')) c,
       parks a, 
       highways b
  WHERE c.rowid1 = a.rowid AND c.rowid2 = b.rowid;

5.2.3 データおよび索引の次元と空間問合せ

空間問合せの要素には、理論上、次の次元があります。

  • 実表ジオメトリ(空間演算子形式のgeometry1)は、2次元、3次元またはそれ以上の次元になる可能性があります。

  • 実表に作成される空間索引(geometry1)は、2次元または3次元になる可能性があります。

  • 問合せウィンドウ(空間演算子形式のgeometry2)は、2次元、3次元またはそれ以上の次元になる可能性があります。

これらの3つの要素における次元の組合せには、サポートされるものとされないものがあります。表5-1に、2次元および3次元の組合せによる結果を示します。

表5-1 データおよび索引の次元と問合せサポート

実表(geometry1)の次元 空間索引の次元 問合せウィンドウ(geometry2)の次元 問合せ結果

2次元

2次元

2次元

2次元問合せが実行されます。

2次元

2次元

3次元

問合せウィンドウのSDO_GTYPE値が適切で、3008未満の場合にサポートされます。

2次元

3次元

2次元

非サポート: 2次元データで3次元索引は許可されません。

2次元

3次元

3次元

非サポート: 2次元データで3次元索引は許可されません。

3次元

2次元

2次元

基となる各ジオメトリで3番目の(Z)次元が無視され、2次元問合せが実行されます。

3次元

2次元

3次元

問合せウィンドウのSDO_GTYPE値が適切で、3008未満の場合にサポートされます。

3次元

3次元

2次元

2次元問合せウィンドウが、0個のZ値を持つ3次元ウィンドウに変換され、3次元問合せが実行されます。

3次元

3次元

3次元

3次元問合せが実行されます。