@@ -15,7 +15,7 @@ summary: 了解 TiDB 全局索引的使用场景、优势、用法、工作原
1515
1616### 查询性能提升
1717
18- 全局索引能够有效提升非分区列的查询效率。当查询涉及非分区列时,全局索引可以快速定位相关数据,避免对所有分区进行全表扫描。这显著减少了 Coprocessor(cop)任务的数量,尤其在分区数量较多的场景下效果更为明显 。
18+ 全局索引能够有效提升非分区列的查询效率。当查询涉及非分区列时,全局索引可以快速定位相关数据,避免对所有分区进行全表扫描。这显著减少了 Coprocessor(cop)任务的数量,尤其适用于分区数量较多的场景 。
1919
2020基准测试显示,当表包含 100 个分区时,在 sysbench 的 ` select_random_points ` 场景下,性能提升最高可达 53 倍。
2121
@@ -25,25 +25,25 @@ summary: 了解 TiDB 全局索引的使用场景、优势、用法、工作原
2525
2626### 降低数据迁移和应用修改成本
2727
28- 在数据迁移和应用修改过程中,全局索引可以显著减少额外调整工作量。如果没有全局索引 ,你可能需要更改分区方案或重写 SQL 查询以规避索引限制。有了全局索引,这些修改可以避免,从而降低开发和运维成本。
28+ 在数据迁移和应用修改过程中,全局索引可以显著减少额外调整工作量。没有全局索引时 ,你可能需要更改分区方案或重写 SQL 查询以规避索引限制。有了全局索引,这些修改可以避免,从而降低开发和运维成本。
2929
3030例如,在将表从 Oracle 数据库迁移到 TiDB 时,可能会遇到不包含分区列的唯一索引,因为 Oracle 支持全局索引。在 TiDB 引入全局索引之前,必须修改表结构以符合 TiDB 的分区规则。现在,TiDB 支持全局索引,迁移时只需将这些索引定义为全局索引,即可保持与 Oracle 一致的表结构行为,大大降低迁移成本。
3131
3232## 全局索引的限制
3333
3434- 如果在索引定义中未显式指定 ` GLOBAL ` 关键字,TiDB 默认创建本地索引。
3535- ` GLOBAL ` 和 ` LOCAL ` 关键字仅适用于分区表,对非分区表无效。换句话说,在非分区表中,全局索引和本地索引没有区别。
36- - ` DROP PARTITION ` 、` TRUNCATE PARTITION ` 和 ` REORGANIZE PARTITION ` 等 DDL 操作也会触发全局索引的更新。这些 DDL 操作需要等待全局索引更新完成后才能返回结果 ,因此执行时间相应增加。尤其在数据归档场景 (如 ` DROP PARTITION ` 和 ` TRUNCATE PARTITION ` )下表现明显。 没有全局索引时,这些操作通常可以立即完成;但有全局索引时,随着需要更新的索引数量增加,执行时间也会增加。
36+ - ` DROP PARTITION ` 、` TRUNCATE PARTITION ` 和 ` REORGANIZE PARTITION ` 等 DDL 操作也会触发全局索引的更新。这些 DDL 操作需要等待全局索引更新完成后才返回结果 ,因此执行时间相应增加。尤其是在数据归档场景 (如 ` DROP PARTITION ` 和 ` TRUNCATE PARTITION ` )下, 没有全局索引时,这些操作通常可以立即完成;但有全局索引时,随着需要更新的索引数量增加,执行时间也会增加。
3737- 包含全局索引的表不支持 ` EXCHANGE PARTITION ` 操作。
3838- 默认情况下,分区表的主键为聚簇索引,且必须包含分区键。如果你需要主键不包含分区键,可以在建表时显式将主键指定为非聚簇全局索引,例如:` PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL ` 。
3939- 如果全局索引添加在表达式列上,或全局索引为前缀索引(如 ` UNIQUE KEY idx_id_prefix (id(10)) GLOBAL ` ),则需要手动收集该全局索引的统计信息。
4040
4141## 功能演进
4242
4343- ** v7.6.0 之前** :TiDB 仅支持分区表的本地索引。这意味着分区表上的唯一键必须包含分区表达式中的所有列。未使用分区键的查询需要扫描所有分区,导致查询性能下降。
44- - ** [ v7.6.0] ( https://docs.pingcap.com/tidb/stable/release-7.6.0 ) ** :引入 [ ` tidb_enable_global_index ` ] ( /system-variables.md#tidb_enable_global_index-new-in-v760 ) 系统变量以开启全局索引。但当时该功能仍在开发中,不建议生产环境使用 。
44+ - ** [ v7.6.0] ( https://docs.pingcap.com/tidb/stable/release-7.6.0 ) ** :引入 [ ` tidb_enable_global_index ` ] ( /system-variables.md#tidb_enable_global_index-new-in-v760 ) 系统变量以开启全局索引。但当时该功能仍在开发中,不建议在生产环境中使用 。
4545- ** [ v8.3.0] ( https://docs.pingcap.com/tidb/stable/release-8.3.0 ) ** :全局索引作为实验特性发布。你可以在定义索引时通过 ` GLOBAL ` 关键字显式创建全局索引。
46- - ** [ v8.4.0] ( https://docs.pingcap.com/tidb/stable/release-8.4.0 ) ** :全局索引功能正式 GA。你可以直接使用 ` GLOBAL ` 关键字创建全局索引,无需设置 ` tidb_enable_global_index ` 系统变量。从该版本起,该系统变量被废弃,值固定为 ` ON ` ,即默认启用全局索引 。
46+ - ** [ v8.4.0] ( https://docs.pingcap.com/tidb/stable/release-8.4.0 ) ** :全局索引功能正式 GA。你可以直接使用 ` GLOBAL ` 关键字创建全局索引,无需设置 ` tidb_enable_global_index ` 系统变量。从该版本起,该系统变量被废弃,值固定为 ` ON ` ,即默认开启全局索引 。
4747- ** [ v8.5.0] ( https://docs.pingcap.com/tidb/stable/release-8.5.0 ) ** :全局索引支持包含分区表达式中的所有列。
4848
4949## 全局索引 vs. 本地索引
@@ -54,7 +54,7 @@ summary: 了解 TiDB 全局索引的使用场景、优势、用法、工作原
5454
5555** 全局索引适用场景** :
5656
57- - ** 数据归档不频繁** :如医疗行业,部分业务数据需保留 30 年,通常按月分区,一次性创建 360 个分区,后续很少进行 ` DROP ` 或 ` TRUNCATE ` 操作。在此场景下,全局索引更适合,因为它能提供跨分区一致性和更高的查询性能 。
57+ - ** 数据归档不频繁** :如医疗行业,部分业务数据需保留 30 年,通常按月分区,一次性创建 360 个分区,后续很少进行 ` DROP ` 或 ` TRUNCATE ` 操作。在此场景下,全局索引更适合,因为它提供跨分区一致性和更高的查询性能 。
5858- ** 跨分区查询** :当查询需要跨多个分区访问数据时,全局索引可以避免对所有分区的全表扫描,提升查询效率。
5959
6060** 本地索引适用场景** :
@@ -64,7 +64,7 @@ summary: 了解 TiDB 全局索引的使用场景、优势、用法、工作原
6464
6565## 全局索引 vs. 聚簇索引
6666
67- 由于聚簇索引和全局索引的底层原理约束 ,单个索引不能同时作为聚簇索引和全局索引。但每种索引在不同查询场景下都能带来不同的性能收益。当你需要同时利用两者优势时,可以将分区列包含在聚簇索引中,并单独创建一个不包含分区列的全局索引 。
67+ 由于聚簇索引和全局索引的底层原理限制 ,单个索引不能同时作为聚簇索引和全局索引。但每种索引在不同查询场景下都能带来不同的性能收益。当你需要同时利用两者优势时,可以将分区列包含在聚簇索引中,并单独创建不包含分区列的全局索引 。
6868
6969假设你有如下表结构:
7070
@@ -80,7 +80,7 @@ PARTITION BY RANGE (UNIX_TIMESTAMP(`ts`))
8080 ...)
8181```
8282
83- 在上述 ` t ` 表中,` id ` 列为唯一值。为了同时优化点查和范围查询,可以在建表语句中定义聚簇索引 ` PRIMARY KEY(id, ts) ` ,并定义一个不包含分区列的全局索引 ` UNIQUE KEY id(id) ` 。这样,基于 ` id ` 的点查会使用全局索引 ` id ` 并选择 ` PointGet ` 执行计划;范围查询则会使用聚簇索引,因为聚簇索引相比全局索引避免了一次额外的回表操作 ,提升了查询效率。
83+ 在上述 ` t ` 表中,` id ` 列为唯一值。为了同时优化点查和范围查询,可以在建表语句中定义聚簇索引 ` PRIMARY KEY(id, ts) ` ,并定义不包含分区列的全局索引 ` UNIQUE KEY id(id) ` 。这样,基于 ` id ` 的点查会使用全局索引 ` id ` 并选择 ` PointGet ` 执行计划;范围查询则会使用聚簇索引,因为聚簇索引相比全局索引避免了一次额外的表查找 ,提升了查询效率。
8484
8585修改后的表结构如下:
8686
@@ -98,7 +98,7 @@ PARTITION BY RANGE (UNIX_TIMESTAMP(`ts`))
9898 ...)
9999```
100100
101- 这种方式既优化了基于 ` id ` 的点查,也提升了范围查询的性能,并确保表的分区列能在基于时间戳的查询中得到有效利用 。
101+ 这种方式既优化了基于 ` id ` 的点查,也提升了范围查询的性能,并确保表的分区列在基于时间戳的查询中得到有效利用 。
102102
103103## 用法
104104
@@ -165,7 +165,7 @@ PARTITION BY HASH (`col3`) PARTITIONS 4
1651651 row in set (0.00 sec)
166166```
167167
168- 或者, 你也可以查询 [ ` INFORMATION_SCHEMA.TIDB_INDEXES ` ] ( /information-schema/information-schema-tidb-indexes.md ) 表,并通过输出中的 ` IS_GLOBAL ` 列来识别全局索引。
168+ 你也可以查询 [ ` INFORMATION_SCHEMA.TIDB_INDEXES ` ] ( /information-schema/information-schema-tidb-indexes.md ) 表,并通过输出中的 ` IS_GLOBAL ` 列来识别全局索引。
169169
170170``` sql
171171SELECT * FROM information_schema .tidb_indexes WHERE table_name= ' t1' ;
@@ -185,19 +185,19 @@ SELECT * FROM information_schema.tidb_indexes WHERE table_name='t1';
185185
186186在对普通表进行分区或对分区表重新分区时,你可以根据需要将索引更新为全局索引或本地索引。
187187
188- 例如,以下 SQL 语句将表 ` t1 ` 按 ` col1 ` 列重新分区,并将全局索引 ` uidx12 ` 和 ` idx1 ` 更新为本地索引,将本地索引 ` uidx3 ` 更新为全局索引。` uidx3 ` 是 ` col3 ` 上的唯一索引 ,为保证 ` col3 ` 在所有分区间的唯一性,` uidx3 ` 必须为全局索引。` uidx12 ` 和 ` idx1 ` 是 ` col1 ` 上的索引 ,可以为全局索引或本地索引。
188+ 例如,以下 SQL 语句将表 ` t1 ` 按 ` col1 ` 列重新分区,并将全局索引 ` uidx12 ` 和 ` idx1 ` 更新为本地索引,将本地索引 ` uidx3 ` 更新为全局索引。` uidx3 ` 是 ` col3 ` 列上的唯一索引 ,为保证 ` col3 ` 在所有分区间的唯一性,` uidx3 ` 必须为全局索引。` uidx12 ` 和 ` idx1 ` 是 ` col1 ` 列上的索引 ,可以为全局索引或本地索引。
189189
190190``` sql
191191ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCAL, uidx3 GLOBAL, idx1 LOCAL);
192192```
193193
194194## 工作原理
195195
196- 本节介绍全局索引的工作原理,包括其设计原则和实现方式 。
196+ 本节介绍全局索引的工作原理,包括设计原则和实现方式 。
197197
198198### 设计原则
199199
200- 在 TiDB 分区表中,本地索引的 key 前缀为 Partition ID,而全局索引的前缀为 Table ID。该设计保证了全局索引数据在 TiKV 上连续分布,从而减少索引查找时的 RPC 请求数量。
200+ 在 TiDB 分区表中,本地索引的 key 前缀为 Partition ID,而全局索引的前缀为 Table ID。该设计保证了全局索引数据在 TiKV 上连续分布,从而减少索引查找所需的 RPC 请求数量。
201201
202202``` sql
203203CREATE TABLE `sbtest ` (
@@ -213,13 +213,13 @@ CREATE TABLE `sbtest` (
213213
214214当执行与 ` k ` 相关的查询(如 ` SELECT * FROM sbtest WHERE k > 1 ` )时,本地索引 ` idx ` 会生成 5 个独立的范围,而全局索引 ` global_idx ` 只生成一个范围。由于 TiDB 中每个范围对应一次或多次 RPC 请求,使用全局索引可以将 RPC 请求数量减少数倍,从而提升索引查询性能。
215215
216- 下图展示了在执行 ` SELECT * FROM sbtest WHERE k > 1 ` 语句时,分别使用 ` idx ` 和 ` global_idx ` 两种索引时的 RPC 请求和数据流动差异 。
216+ 下图展示了在执行 ` SELECT * FROM sbtest WHERE k > 1 ` 语句时,分别使用 ` idx ` 和 ` global_idx ` 两种索引时的 RPC 请求和数据流差异 。
217217
218218![ Mechanism of Global Indexes] ( https://docs-download.pingcap.com/media/images/docs/global-index-mechanism.png )
219219
220220### 编码方式
221221
222- 在 TiDB 中,索引条目以键值对形式编码 。对于分区表,TiKV 层将每个分区视为独立的物理表,拥有各自的 ` partitionID ` 。因此,分区表索引条目的编码方式如下:
222+ 在 TiDB 中,索引条目以键值对的形式编码 。对于分区表,每个分区在 TiKV 层被视为独立的物理表,拥有自己的 ` partitionID ` 。因此,分区表索引条目的编码方式如下:
223223
224224```
225225唯一键
@@ -293,7 +293,7 @@ CREATE TABLE `sbtest` (
293293/* Partition by range(`id`) xxxx */
294294```
295295
296- 压力 SQL 如下:
296+ 测试用 SQL 如下:
297297
298298``` sql
299299SELECT id, k, c, pad
@@ -307,14 +307,14 @@ WHERE k IN (xx, xx, xx)
307307| ----------------------------------------------------------------- | ------ | ------- | ------- | ------- |
308308| 聚簇非分区表 | 225 | 19,999 | 30,293 | 7.92 |
309309| 按主键范围分区的聚簇表 | 68 | 480 | 511 | 114.87 |
310- | 按主键范围分区且 ` k ` 、 ` c ` 上有全局索引的聚簇表 | 207 | 17,798 | 27,707 | 11.73 |
310+ | 按主键范围分区且 ` k ` , ` c ` 上有全局索引的聚簇表 | 207 | 17,798 | 27,707 | 11.73 |
311311
312312哈希分区(100 个分区):
313313
314314| 表类型 | 并发 1 | 并发 32 | 并发 64 | 平均 RU |
315315| ---------------------------------------------------------------- | ------ | ------- | ------- | ------- |
316316| 聚簇非分区表 | 166 | 20,361 | 28,922 | 7.86 |
317317| 按主键哈希分区的聚簇表 | 60 | 244 | 283 | 119.73 |
318- | 按主键哈希分区且 ` k ` 、 ` c ` 上有全局索引的聚簇表 | 156 | 18,233 | 15,581 | 10.77 |
318+ | 按主键哈希分区且 ` k ` , ` c ` 上有全局索引的聚簇表 | 156 | 18,233 | 15,581 | 10.77 |
319319
320- 上述测试表明,在高并发环境下,全局索引可以显著提升分区表的查询性能,性能提升最高可达 50 倍。同时,全局索引大幅降低了 Request Unit(RU)消耗。随着分区数量的增加,性能收益更加明显 。
320+ 上述测试表明,在高并发环境下,全局索引可以显著提升分区表的查询性能,性能提升最高可达 50 倍。同时,全局索引大幅降低了 Request Unit(RU)消耗。随着分区数量的增加,性能优势更加明显 。
0 commit comments