全局二級(jí)索引(GSI)
PolarDB MySQL版支持在分區(qū)表上創(chuàng)建全局二級(jí)索引(Global Secondary Index,簡(jiǎn)稱GSI)。使用全局二級(jí)索引可以實(shí)現(xiàn)透明分區(qū)表,即您可以像使用單表一樣使用分區(qū)表,大大減少分區(qū)鍵對(duì)分區(qū)表的使用限制。
全局二級(jí)索引功能當(dāng)前處于灰度發(fā)布階段,如有需求,請(qǐng)前往配額中心,根據(jù)配額ID
polardb_mysql_gsi
找到配額名稱,在對(duì)應(yīng)的操作列單擊申請(qǐng)來開通該功能。如需了解更多關(guān)于全局二級(jí)索引(GSI)的內(nèi)容,請(qǐng)搜索釘釘群號(hào)加群進(jìn)行咨詢。釘釘群號(hào):24490017825。
背景信息
分區(qū)表上傳統(tǒng)的索引為局部索引。局部索引對(duì)于邏輯表而言也是分區(qū)的,局部索引的分區(qū)方式與表的分區(qū)方式相同。局部索引單個(gè)分區(qū)的數(shù)據(jù)由分區(qū)表單個(gè)分區(qū)的數(shù)據(jù)構(gòu)建而成,且局部索引的分區(qū)與分區(qū)表的分區(qū)一一對(duì)應(yīng),所以,局部索引的索引數(shù)據(jù)只能保證在單個(gè)分區(qū)內(nèi)有序,如果您想創(chuàng)建局部唯一索引,則索引字段必須包含全部的分區(qū)鍵。
當(dāng)分區(qū)表上只存在局部索引時(shí),使用分區(qū)表因受到分區(qū)鍵的限制,會(huì)遇到一些棘手的問題,如下:
查詢條件不包含分區(qū)鍵時(shí),查詢數(shù)據(jù)需要掃描分區(qū)表上的所有分區(qū),這將帶來明顯的讀放大問題,且分區(qū)越多,讀放大越嚴(yán)重。
查詢結(jié)果對(duì)索引字段有順序要求時(shí),即使局部索引中每個(gè)分區(qū)的數(shù)據(jù)是有序的,也無法保證跨分區(qū)查詢的索引數(shù)據(jù)全局有序,可能會(huì)觸發(fā)額外的全局排序操作。
局部唯一索引必須包含全部的分區(qū)鍵,否則無法保證所有分區(qū)的全局唯一性約束。
PolarDB MySQL版的全局索引與局部索引相對(duì),全局索引不分區(qū),由全部分區(qū)的數(shù)據(jù)構(gòu)建而成。所以,全局索引上的索引數(shù)據(jù)對(duì)全局的分區(qū)表有序,如果您想創(chuàng)建全局唯一索引,索引字段不需要包含全部的分區(qū)鍵。
前提條件
集群版本需為PolarDB MySQL版8.0.2版本且修訂版本為8.0.2.2.7及以上。您可以通過查詢版本號(hào)來確認(rèn)集群版本。
使用限制
全局二級(jí)索引僅支持在InnoDB引擎上創(chuàng)建的分區(qū)表,不支持混合分區(qū)表。
全局二級(jí)索引不能為全文索引或空間索引。
不支持在壓縮表、臨時(shí)表、加密表、REDUNDANT以及COMPRESSED行格式的表上創(chuàng)建全局二級(jí)索引。
創(chuàng)建全局二級(jí)索引的列不能為分區(qū)表的主鍵。
創(chuàng)建全局二級(jí)索引的表不支持生成列(Generated Column)。
分區(qū)級(jí)別的DDL變更(新增RANGE或LIST分區(qū)除外)會(huì)導(dǎo)致已創(chuàng)建的全局二級(jí)索引失效,您需要先刪除表上所有的全局二級(jí)索引,再重建二級(jí)索引,或直接使用
UPDATE GLOBAL INDEX
語法重建二級(jí)索引。
增強(qiáng)特性
支持使用并行DDL來并行創(chuàng)建全局二級(jí)索引。
支持在已創(chuàng)建全局二級(jí)索引的分區(qū)表上使用秒級(jí)加字段功能。
已創(chuàng)建全局二級(jí)索引的RANGE或LIST分區(qū)表,在新增分區(qū)時(shí)支持使用分區(qū)級(jí)別的MDL鎖。
支持將已創(chuàng)建全局二級(jí)索引的表轉(zhuǎn)換為INTERVAL RANGE分區(qū)表,同時(shí)支持在INTERVAL RANGE分區(qū)表上創(chuàng)建全局二級(jí)索引。
對(duì)已創(chuàng)建全局二級(jí)索引的分區(qū)表執(zhí)行分區(qū)級(jí)別的DDL變更時(shí),支持使用
UPDATE GLOBAL INDEX
語法重建表上的全局二級(jí)索引。示例如下:創(chuàng)建以
a
字段為分區(qū)鍵的RANGE分區(qū)表t1
,同時(shí)在b
字段上創(chuàng)建全局索引k1
。CREATE TABLE t1( a INT PRIMARY KEY, b INT, INDEX k1(b) GLOBAL ) PARTITION BY RANGE (`a`) (PARTITION p0 VALUES LESS THAN (5) ENGINE = InnoDB, PARTITION p1 VALUES LESS THAN (10) ENGINE = InnoDB);
刪除
t1
表上的p1
分區(qū)并重建全局二級(jí)索引。ALTER TABLE t1 DROP PARTITION p1 UPDATE GLOBAL INDEX;
語法
創(chuàng)建索引時(shí),通過在索引名稱后添加LOCAL或GLOBAL關(guān)鍵字來指定局部索引或全局索引。
如果在創(chuàng)建索引時(shí),沒有指定全局二級(jí)索引,則默認(rèn)創(chuàng)建局部索引。
示例
創(chuàng)建以
a
字段為分區(qū)鍵的分區(qū)表t1
。同時(shí)在b
字段上創(chuàng)建全局索引k1
。CREATE TABLE t1( a INT PRIMARY KEY, b INT, INDEX k1(b) GLOBAL ) PARTITION BY HASH(a) PARTITIONS 3;
創(chuàng)建以
a
字段為分區(qū)鍵的分區(qū)表t1
,再在t1
的b
字段上創(chuàng)建全局索引k1
和全局唯一索引k2
。CREATE TABLE t1( a INT PRIMARY KEY, b INT ) PARTITION BY HASH(a) PARTITIONS 3; ALTER TABLE t1 ADD INDEX k1(b) GLOBAL; CREATE UNIQUE INDEX k2 ON t1(b) GLOBAL;
性能測(cè)試
測(cè)試對(duì)象
數(shù)據(jù)量100萬條,表結(jié)構(gòu)和表數(shù)據(jù)相同的2張分區(qū)表。在1張分區(qū)表上創(chuàng)建局部索引,另外的1張分區(qū)表上創(chuàng)建全局二級(jí)索引。
此處以創(chuàng)建分區(qū)表mytest1.big_table_1
和mytest2.big_table_1
為例,其中,表mytest1.big_table_1
為創(chuàng)建局部索引的表,表mytest2.big_table_1
為創(chuàng)建全局二級(jí)索引的表。
CREATE TABLE mytest1.big_table_1(
a INT PRIMARY KEY,
b INT,
c INT,
INDEX k1(b) LOCAL
) PARTITION BY HASH(a) PARTITIONS 32;
CREATE TABLE mytest2.big_table_1(
a INT PRIMARY KEY,
b INT,
c INT,
INDEX k1(b) GLOBAL
) PARTITION BY HASH(a) PARTITIONS 32;
測(cè)試方法
針對(duì)SELECT、UPDATE和DELETE語句的查詢條件中不包含分區(qū)鍵的場(chǎng)景,測(cè)試不同分區(qū)數(shù)量下,使用局部索引和全局索引的耗時(shí)。
測(cè)試結(jié)果
SELECT語句的查詢條件中不包含分區(qū)鍵,使用局部索引和全局索引的耗時(shí)。
UPDATE語句的查詢條件中不包含分區(qū)鍵,使用局部索引和全局索引的耗時(shí)。
DELETE語句的查詢條件中不包含分區(qū)鍵,使用局部索引和全局索引的耗時(shí)。
由以上的測(cè)試結(jié)果可以看出:在查詢條件不包含分區(qū)鍵的場(chǎng)景中,執(zhí)行SELECT、UPDATE和DELETE命令時(shí),使用全局二級(jí)索引的執(zhí)行耗時(shí)較短,且數(shù)據(jù)量越大執(zhí)行耗時(shí)差異越明顯。