グローバルインデックスの作成ルールは、インデックスプロパティにGLOBALキーワードを指定することです。ローカルインデックスと比較して、グローバルインデックスの最大の特徴は、グローバルインデックスのパーティションルールがテーブルのパーティションルールと独立している点です。グローバルインデックスは独自のパーティションルールとパーティション数を指定でき、必ずしもテーブルのパーティションルールと一致させる必要はありません。
グローバルインデックスの作成
主表にパーティションキーが指定されていない場合、または指定されたパーティション数が1の場合、主表も1つのパーティションしか持ちません。この場合、グローバルインデックスのデータと主表のデータの物理的位置は密接に結びついており、移行やレプリカリーダーの切り替えが発生した場合でも、それらは一体として変換され、中間状態は存在しません。グローバルインデックスのパーティションルールと主表のパーティションルールが同じで、かつパーティション数が同じ場合は、ローカルインデックスを作成することを推奨します。一つにはグローバルインデックスの方がメンテナンスコストが高いこと、もう一つにはグローバルインデックスでは主表のパーティションと物理的に同じ位置に配置される保証がないことが理由です。
説明
グローバルインデックスを作成する際、対象のテーブルが SHARDING = 'NONE' プロパティを持つテーブルグループに属している場合、作成されたグローバルインデックスもそのテーブルグループに紐づけられます。テーブルグループプロパティの詳細については、テーブルグループのSHARDINGプロパティの変更を参照してください。
Oracleモードでは、インデックスプロパティキーワードが指定されていない場合、デフォルトでGLOBALプロパティが適用され、作成されるインデックスはグローバルインデックスとなり、インデックステーブルは1つのパーティションしか持ちません。例:
obclient> CREATE TABLE tbl1(col1 INT,col2 INT)
PARTITION BY HASH(col2) PARTITIONS 5;
Query OK, 0 rows affected
obclient> CREATE INDEX idx1 ON tbl1(col1);
Query OK, 0 rows affected
グローバルインデックスの作成
Hashパーティションのパーティションテーブル tbl1_h を作成し、Rangeパーティションを使用するグローバルインデックス tbl1_h_idx1 を作成します。
obclient> CREATE TABLE tbl1_h(col1 INT PRIMARY KEY,col2 INT)
PARTITION BY HASH(col1) PARTITIONS 5;
Query OK, 0 rows affected
obclient> CREATE INDEX tbl1_h_idx1 ON tbl1_h(col2) GLOBAL
PARTITION BY RANGE(col2)
(PARTITION p0 VALUES LESS THAN(100),
PARTITION p1 VALUES LESS THAN(200),
PARTITION p2 VALUES LESS THAN(300)
);
Query OK, 0 rows affected
グローバル一意インデックスの作成
非テンプレートの Range + List パーティションテーブル tbl2_f_rl を作成し、グローバル一意インデックス tbl2_f_rl_idx1 を作成します。
obclient> CREATE TABLE tbl2_f_rl(col1 INT,col2 INT)
PARTITION BY RANGE(col1)
SUBPARTITION BY LIST(col2)
(PARTITION p0 VALUES LESS THAN(100)
(SUBPARTITION sp0 VALUES(1,3),
SUBPARTITION sp1 VALUES(4,6),
SUBPARTITION sp2 VALUES(7,9)),
PARTITION p1 VALUES LESS THAN(200)
(SUBPARTITION sp3 VALUES(1,3),
SUBPARTITION sp4 VALUES(4,6),
SUBPARTITION sp5 VALUES(7,9))
);
Query OK, 0 rows affected
obclient> CREATE UNIQUE INDEX tbl2_f_rl_idx1 ON tbl2_f_rl(col1) GLOBAL;
Query OK, 0 rows affected
パーティションプルーニング
グローバルインデックスのパーティションキーは必ずインデックスキー自体であるため、グローバルインデックスを使用する際には、インデックスのパーティションキーを指定するクエリ条件を指定します。これにより、インデックスのパーティションルールに基づいてパーティションプルーニングを行うことができます。インデックスキー値を取得した後、インデックステーブルに格納されている主キー情報を利用して主表のパーティション位置を計算し、主表に対しても高速なパーティション位置付けを行うことができます。これにより、主表のすべてのパーティションをスキャンすることを回避できます。したがって、主表のパーティションキーを指定できないクエリにおいて、グローバルインデックスは一定の条件下でクエリの検索効率を向上させることができます。
例:
obclient> EXPLAIN SELECT /*+index(t1 gkey)*/ * FROM t1 WHERE b=1;
+---------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------+
| ========================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ---------------------------------------------------------- |
| |0 |DISTRIBUTED TABLE SCAN|t1(GKEY)|4950 |38645 | |
| ========================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([t1.A], [t1.B], [t1.C]), filter(nil), rowset=256 |
| access([t1.A], [t1.B], [t1.C]), partitions(p0) |
| is_index_back=true, is_global_index=true, |
| range_key([t1.B], [t1.A]), range(1,MIN ; 1,MAX), |
| range_cond([t1.B = 1]) |
+---------------------------------------------------------------+
上記のクエリでは、まず WHERE 条件の b=1 条件によりグローバルインデックスのパーティション p1 がプルーニングされ、次にグローバルインデックステーブルに対して table scan 操作を実行して対応する主キーを取得します。主キーを利用して主表に対して精密なパーティションスキャンを行い、主表のすべてのパーティションをスキャンすることを回避します。