グローバルインデックスの作成ルールは、インデックス属性にGLOBALキーワードを指定することです。ローカルインデックスと比較して、グローバルインデックスの最大の特徴は、グローバルインデックスのパーティションルールがテーブルのパーティションルールと独立している点です。グローバルインデックスは独自のパーティションルールとパーティション数を指定でき、必ずしもテーブルのパーティションルールと一致させる必要はありません。
グローバルインデックスの作成
主表にパーティションキーが指定されていない場合、または指定されたパーティション数が1の場合、主表も1つのパーティションしか持ちません。この場合、グローバルインデックスのデータと主表のデータの物理的位置は密接に結びついており、移行やレプリカリーダーの切り替えが発生した場合でも、それらは一体として変換され、中間状態は存在しません。グローバルインデックスのパーティションルールと主表のパーティションルールが同じで、かつパーティション数も同じ場合は、ローカルインデックスを作成することを推奨します。一つにはグローバルインデックスの方がメンテナンスコストが高いため、もう一つにはグローバルインデックスでは主表のパーティションと物理的に同じ位置に配置される保証がないためです。
説明
グローバルインデックスを作成する際、対象のテーブルが SHARDING = 'NONE' プロパティを持つテーブルグループ内にある場合、作成されたグローバルインデックスもそのテーブルグループに紐づけられます。テーブルグループプロパティの詳細については、テーブルグループのSHARDINGプロパティの変更を参照してください。
グローバルインデックスの作成
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 IN(1,3),
SUBPARTITION sp1 VALUES IN(4,6),
SUBPARTITION sp2 VALUES IN(7,9)),
PARTITION p1 VALUES LESS THAN(200)
(SUBPARTITION sp3 VALUES IN(1,3),
SUBPARTITION sp4 VALUES IN(4,6),
SUBPARTITION sp5 VALUES IN(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 操作を実行して対応する主キーを取得します。主キーを利用して主表に対して精密なパーティションスキャンを行い、主表のすべてのパーティションをスキャンすることを回避します。