Skip to content

Commit 6209ced

Browse files
authored
partitioned-table: global index supports non-unique index (#19507)
1 parent 7b8de03 commit 6209ced

File tree

1 file changed

+16
-17
lines changed

1 file changed

+16
-17
lines changed

partitioned-table.md

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,13 +1685,13 @@ CREATE TABLE t (a varchar(20), b blob,
16851685
ERROR 8264 (HY000): Global Index is needed for index 'a', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
16861686
```
16871687

1688-
#### 全局索引
1688+
### 全局索引
16891689

16901690
在引入全局索引 (Global Index) 之前,TiDB 会为每个分区创建一个局部索引 (Local Index),即一个分区对应一个局部索引。这种索引方式存在一个[使用限制](#分区键主键和唯一键):主键和唯一键必须包含所有的分区键,以确保数据的全局唯一性。此外,当查询的数据跨越多个分区时,TiDB 需要扫描各个分区的数据才能返回结果。
16911691

1692-
为解决这些问题,TiDB 从 v8.3.0 开始引入全局索引。全局索引能覆盖整个表的数据,使得主键和唯一键在不包含分区键的情况下仍能保持全局唯一性。此外,全局索引可以在一次操作中访问多个分区的索引数据,而无需对每个分区的本地索引逐一查找,显著提升了针对非分区键的查询性能。
1692+
为解决这些问题,TiDB 从 v8.3.0 开始引入全局索引。全局索引能覆盖整个表的数据,使得主键和唯一键在不包含分区键的情况下仍能保持全局唯一性。此外,全局索引可以在一次操作中访问多个分区的索引数据,而无需对每个分区的局部索引逐一查找,显著提升了针对非分区键的查询性能。从 v9.0.0 开始,非唯一索引也可以创建为全局索引
16931693

1694-
如果你需要为主键或唯一键创建全局索引,可以通过在索引定义中添加 `GLOBAL` 关键字来实现。
1694+
如果你需要创建全局索引,可以通过在索引定义中添加 `GLOBAL` 关键字来实现。
16951695

16961696
> **注意:**
16971697
>
@@ -1704,13 +1704,14 @@ CREATE TABLE t1 (
17041704
col3 INT NOT NULL,
17051705
col4 INT NOT NULL,
17061706
UNIQUE KEY uidx12(col1, col2) GLOBAL,
1707-
UNIQUE KEY uidx3(col3)
1707+
UNIQUE KEY uidx3(col3),
1708+
KEY idx1(col1) GLOBAL
17081709
)
17091710
PARTITION BY HASH(col3)
17101711
PARTITIONS 4;
17111712
```
17121713

1713-
在上面示例中,唯一索引 `uidx12` 将成为全局索引,但 `uidx3` 仍是常规的唯一索引。
1714+
在上面示例中,唯一索引 `uidx12` 和非唯一索引 `idx1` 将成为全局索引,但 `uidx3` 仍是常规的唯一索引。
17141715

17151716
请注意,**聚簇索引**不能成为全局索引,如下例所示:
17161717

@@ -1742,7 +1743,8 @@ Create Table: CREATE TABLE `t1` (
17421743
`col3` int NOT NULL,
17431744
`col4` int NOT NULL,
17441745
UNIQUE KEY `uidx12` (`col1`,`col2`) /*T![global_index] GLOBAL */,
1745-
UNIQUE KEY `uidx3` (`col3`)
1746+
UNIQUE KEY `uidx3` (`col3`),
1747+
KEY `idx1` (`col1`) /*T![global_index] GLOBAL */
17461748
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
17471749
PARTITION BY HASH (`col3`) PARTITIONS 4
17481750
1 row in set (0.00 sec)
@@ -1761,26 +1763,23 @@ SELECT * FROM information_schema.tidb_indexes WHERE table_name='t1';
17611763
| test | t1 | 0 | uidx12 | 1 | col1 | NULL | | NULL | 1 | YES | NO | 1 |
17621764
| test | t1 | 0 | uidx12 | 2 | col2 | NULL | | NULL | 1 | YES | NO | 1 |
17631765
| test | t1 | 0 | uidx3 | 1 | col3 | NULL | | NULL | 2 | YES | NO | 0 |
1766+
| test | t1 | 1 | idx1 | 1 | col1 | NULL | | NULL | 3 | YES | NO | 1 |
17641767
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
17651768
3 rows in set (0.00 sec)
17661769
```
17671770

1768-
在对未分区的表进行分区,或对已分区的表进行重新分区时,可以根据需要将索引更新为全局索引或将其还原为本地索引:
1771+
在对普通表进行分区或者对分区表进行重新分区时,可以根据需要将索引更新为全局索引或局部索引。
1772+
1773+
例如,下面的 SQL 语句会基于 `col1` 列对表 `t1` 进行重新分区,并将该表中的全局索引 `uidx12``idx1` 更新为局部索引,将局部索引 `uidx3` 更新为全局索引。`uidx3` 是基于 `col3` 列的唯一索引,为了保证 `col3` 在所有分区中的唯一性,`uidx3` 必须为全局索引;`uidx12``idx1` 是基于 `col1` 列的索引,因此可以是全局索引或局部索引。
17691774

17701775
```sql
1771-
ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCAL, uidx3 GLOBAL);
1776+
ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCAL, uidx3 GLOBAL, idx1 LOCAL);
17721777
```
17731778

1774-
##### 全局索引的限制
1779+
#### 全局索引的限制
17751780

17761781
- 如果索引定义中未显式指定 `GLOBAL` 关键字,TiDB 将默认创建局部索引 (Local Index)。
17771782
- `GLOBAL``LOCAL` 关键字仅适用于分区表,对非分区表没有影响。即在非分区表中,全局索引和局部索引之间没有区别。
1778-
- 当前仅支持为唯一列创建全局索引 (Unique Global Index)。如果需要对非唯一列创建全局索引,可以通过包含主键形成复合索引。例如,如果非唯一列是 `col3` 而主键是 `col1`,可以通过执行以下 SQL 语句为 `col3` 创建全局索引:
1779-
1780-
```sql
1781-
ALTER TABLE ... ADD UNIQUE INDEX(col3, col1) GLOBAL;
1782-
```
1783-
17841783
- 以下 DDL 操作会触发全局索引的更新:`DROP PARTITION``TRUNCATE PARTITION``REORGANIZE PARTITION`。这些 DDL 需等待全局索引更新完成后才会返回结果,耗时会相应增加。尤其是在数据归档场景下,如 `DROP PARTITION``TRUNCATE PARTITION`,若没有全局索引,通常可以立即完成;但使用全局索引后,耗时会随着所需更新的索引数量的增加而增加。
17851784
- 包含全局索引的表不支持 `EXCHANGE PARTITION`
17861785
- 默认情况下,分区表的主键为聚簇索引,且必须包含分区键。如果要求主键不包含分区建,可以在建表时显式指定主键为非聚簇的全局索引,例如:`PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`
@@ -1914,7 +1913,7 @@ select * from t;
19141913
5 rows in set (0.00 sec)
19151914
```
19161915

1917-
### 动态裁剪模式
1916+
## 动态裁剪模式
19181917

19191918
TiDB 访问分区表有两种模式,`dynamic``static`。从 v6.3.0 开始,默认使用 `dynamic` 模式。但是注意,`dynamic` 模式仅在表级别汇总统计信息(即分区表的全局统计信息)收集完成的情况下生效。如果在全局统计信息未收集完成的情况下启用 `dynamic` 动态裁剪模式,TiDB 仍然会维持 `static` 静态裁剪的状态,直到全局统计信息收集完成。关于全局统计信息的更多信息,请参考[动态裁剪模式下的分区表统计信息](/statistics.md#收集动态裁剪模式下的分区表统计信息)
19201919

@@ -2119,7 +2118,7 @@ mysql> explain select /*+ TIDB_INLJ(t1, t2) */ t1.* from t1, t2 where t2.code =
21192118

21202119
目前,静态裁剪模式不支持执行计划缓存,包括 Prepare 语句和非 Prepare 语句。
21212120

2122-
#### 为动态裁剪模式更新所有分区表的统计信息
2121+
### 为动态裁剪模式更新所有分区表的统计信息
21232122

21242123
1. 找到所有的分区表:
21252124

0 commit comments

Comments
 (0)