グローバルインデックスは、インデックス属性に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 操作を実行して対応する主キーを取得します。この主キーを用いてメインテーブルを精密にパーティションスキャンし、メインテーブルのすべてのパーティションをスキャンすることを回避します。