Skip to content

Commit 55bd685

Browse files
authored
sql: make global indexes a new doc and add more contents (#20855) (#21169)
1 parent cb3c595 commit 55bd685

17 files changed

+339
-114
lines changed

TOC.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,7 @@
981981
- [下推到 TiKV 的表达式列表](/functions-and-operators/expressions-pushed-down.md)
982982
- [Oracle 与 TiDB 函数和语法差异对照](/oracle-functions-to-tidb.md)
983983
- [聚簇索引](/clustered-indexes.md)
984+
- [全局索引](/global-indexes.md)
984985
- [向量索引](/vector-search/vector-search-index.md)
985986
- [约束](/constraints.md)
986987
- [生成列](/generated-columns.md)

basic-features.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ summary: 了解 TiDB 的功能概览。
6363
| [多值索引](/sql-statements/sql-statement-create-index.md#多值索引) | Y | Y | Y | Y | N | N | N |
6464
| [外键约束](/foreign-key.md) | Y | E | E | E | N | N | N |
6565
| [TiFlash 延迟物化](/tiflash/tiflash-late-materialization.md) | Y | Y | Y | Y | N | N | N |
66-
| [全局索引 (Global Index)](/partitioned-table.md#全局索引) | Y | N | N | N | N | N | N |
66+
| [全局索引 (Global Index)](/global-indexes.md) | Y | N | N | N | N | N | N |
6767
| [向量索引](/vector-search/vector-search-index.md) | E | N | N | N | N | N | N |
6868

6969
## SQL 语句
@@ -171,7 +171,7 @@ summary: 了解 TiDB 的功能概览。
171171
| [Range INTERVAL 分区](/partitioned-table.md#range-interval-分区) | Y | Y | Y | Y | E | N | N |
172172
| [分区表转换为非分区表](/partitioned-table.md#将分区表转换为非分区表) | Y | Y | Y | N | N | N | N |
173173
| [对现有表进行分区](/partitioned-table.md#对现有表进行分区) | Y | Y | Y | N | N | N | N |
174-
| [全局索引 (Global Index)](/partitioned-table.md#全局索引) | Y | N | N | N | N | N | N |
174+
| [全局索引 (Global Index)](/global-indexes.md) | Y | N | N | N | N | N | N |
175175

176176
## 统计信息
177177

best-practices/tidb-best-practices.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通
8383

8484
+ 通过索引查询和直接扫描 Table 的区别
8585

86-
TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。
86+
TiDB 实现了[全局索引](/global-indexes.md),所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。
8787

8888
如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。
8989

choose-index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Skyline-Pruning 是一个针对索引的启发式过滤规则,能降低错误
8181

8282
- 选择该索引是否能满足一定的顺序。因为索引的读取可以保证某些列集合的顺序,所以满足查询要求顺序的索引在这个维度上优于不满足的索引。
8383

84-
- 该索引是否为[全局索引](/partitioned-table.md#全局索引)。在分区表中,全局索引相比普通索引能有效的降低一个 SQL 的 cop task 数量,进而提升整体性能。
84+
- 该索引是否为[全局索引](/global-indexes.md)。在分区表中,全局索引相比普通索引能有效的降低一个 SQL 的 cop task 数量,进而提升整体性能。
8585

8686
对于上述维度,如果索引 `idx_a` 在这四个维度上都不比 `idx_b` 差,且有一个维度比 `idx_b` 好,那么 TiDB 会优先选择 `idx_a`。在执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果 Skyline-Pruning 排除了某些索引,TiDB 会输出一条 NOTE 级别的 warning 提示哪些索引在 Skyline-Pruning 排除之后保留下来。
8787

global-indexes.md

Lines changed: 320 additions & 0 deletions
Large diffs are not rendered by default.

media/global-index-mechanism.png

228 KB
Loading
21.2 KB
Loading

partitioned-table.md

Lines changed: 3 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,7 +1175,7 @@ ALTER TABLE member_level PARTITION BY RANGE(level)
11751175
PARTITION pMax VALUES LESS THAN (MAXVALUE));
11761176
```
11771177

1178-
对普通表进行分区或者对分区表进行重新分区时,可以根据需要将索引更新为全局索引或普通索引
1178+
对普通表进行分区或者对分区表进行重新分区时,可以根据需要将索引更新为[全局索引](/global-indexes.md)或普通索引
11791179

11801180
```sql
11811181
CREATE TABLE t1 (
@@ -1473,7 +1473,7 @@ SELECT store_id, COUNT(department_id) AS c
14731473

14741474
> **注意:**
14751475
>
1476-
> 使用[全局索引](#全局索引)时,可以忽略该规则。
1476+
> 使用[全局索引](/global-indexes.md)时,可以忽略该规则。
14771477
14781478
这里所指的唯一也包含了主键,因为根据主键的定义,主键必须是唯一的。例如,下面这些建表语句就是无效的:
14791479

@@ -1686,103 +1686,7 @@ ERROR 8264 (HY000): Global Index is needed for index 'a', since the unique index
16861686

16871687
### 全局索引
16881688

1689-
在引入全局索引 (Global Index) 之前,TiDB 会为每个分区创建一个局部索引 (Local Index),即一个分区对应一个局部索引。这种索引方式存在一个[使用限制](#分区键主键和唯一键):主键和唯一键必须包含所有的分区键,以确保数据的全局唯一性。此外,当查询的数据跨越多个分区时,TiDB 需要扫描各个分区的数据才能返回结果。
1690-
1691-
为解决这些问题,TiDB 从 v8.3.0 开始引入全局索引。全局索引能覆盖整个表的数据,使得主键和唯一键在不包含分区键的情况下仍能保持全局唯一性。此外,全局索引可以在一次操作中访问多个分区的索引数据,而无需对每个分区的局部索引逐一查找,显著提升了针对非分区键的查询性能。从 v8.5.4 开始,非唯一索引也可以创建为全局索引。
1692-
1693-
如果你需要创建全局索引,可以通过在索引定义中添加 `GLOBAL` 关键字来实现。
1694-
1695-
> **注意:**
1696-
>
1697-
> 全局索引对分区管理有影响,执行 `DROP``TRUNCATE``REORGANIZE PARTITION` 操作也会触发表级别全局索引的更新,这意味着这些 DDL 操作只有在对应表的全局索引完全更新后才会返回结果。
1698-
1699-
```sql
1700-
CREATE TABLE t1 (
1701-
col1 INT NOT NULL,
1702-
col2 DATE NOT NULL,
1703-
col3 INT NOT NULL,
1704-
col4 INT NOT NULL,
1705-
UNIQUE KEY uidx12(col1, col2) GLOBAL,
1706-
UNIQUE KEY uidx3(col3),
1707-
KEY idx1(col1) GLOBAL
1708-
)
1709-
PARTITION BY HASH(col3)
1710-
PARTITIONS 4;
1711-
```
1712-
1713-
在上面示例中,唯一索引 `uidx12` 和非唯一索引 `idx1` 将成为全局索引,但 `uidx3` 仍是常规的唯一索引。
1714-
1715-
请注意,**聚簇索引**不能成为全局索引,如下例所示:
1716-
1717-
```sql
1718-
CREATE TABLE t2 (
1719-
col1 INT NOT NULL,
1720-
col2 DATE NOT NULL,
1721-
PRIMARY KEY (col2) CLUSTERED GLOBAL
1722-
) PARTITION BY HASH(col1) PARTITIONS 5;
1723-
```
1724-
1725-
```
1726-
ERROR 1503 (HY000): A CLUSTERED INDEX must include all columns in the table's partitioning function
1727-
```
1728-
1729-
聚簇索引不能成为全局索引,是因为如果聚簇索引是全局索引,则表将不再分区。这是因为聚簇索引的键是分区级别的行数据的键,但全局索引是表级别的,这就造成了冲突。如果需要将主键设置为全局索引,则需要显式设置该主键为非聚簇索引,如 `PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`
1730-
1731-
你可以通过 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 输出中的 `GLOBAL` 索引选项来识别全局索引。
1732-
1733-
```sql
1734-
SHOW CREATE TABLE t1\G
1735-
```
1736-
1737-
```
1738-
Table: t1
1739-
Create Table: CREATE TABLE `t1` (
1740-
`col1` int NOT NULL,
1741-
`col2` date NOT NULL,
1742-
`col3` int NOT NULL,
1743-
`col4` int NOT NULL,
1744-
UNIQUE KEY `uidx12` (`col1`,`col2`) /*T![global_index] GLOBAL */,
1745-
UNIQUE KEY `uidx3` (`col3`),
1746-
KEY `idx1` (`col1`) /*T![global_index] GLOBAL */
1747-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
1748-
PARTITION BY HASH (`col3`) PARTITIONS 4
1749-
1 row in set (0.00 sec)
1750-
```
1751-
1752-
或查询 [`INFORMATION_SCHEMA.TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) 表并查看输出中的 `IS_GLOBAL` 列来识别全局索引。
1753-
1754-
```sql
1755-
SELECT * FROM information_schema.tidb_indexes WHERE table_name='t1';
1756-
```
1757-
1758-
```
1759-
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
1760-
| TABLE_SCHEMA | TABLE_NAME | NON_UNIQUE | KEY_NAME | SEQ_IN_INDEX | COLUMN_NAME | SUB_PART | INDEX_COMMENT | Expression | INDEX_ID | IS_VISIBLE | CLUSTERED | IS_GLOBAL |
1761-
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
1762-
| test | t1 | 0 | uidx12 | 1 | col1 | NULL | | NULL | 1 | YES | NO | 1 |
1763-
| test | t1 | 0 | uidx12 | 2 | col2 | NULL | | NULL | 1 | YES | NO | 1 |
1764-
| test | t1 | 0 | uidx3 | 1 | col3 | NULL | | NULL | 2 | YES | NO | 0 |
1765-
| test | t1 | 1 | idx1 | 1 | col1 | NULL | | NULL | 3 | YES | NO | 1 |
1766-
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
1767-
3 rows in set (0.00 sec)
1768-
```
1769-
1770-
在对普通表进行分区或者对分区表进行重新分区时,可以根据需要将索引更新为全局索引或局部索引。
1771-
1772-
例如,下面的 SQL 语句会基于 `col1` 列对表 `t1` 进行重新分区,并将该表中的全局索引 `uidx12``idx1` 更新为局部索引,将局部索引 `uidx3` 更新为全局索引。`uidx3` 是基于 `col3` 列的唯一索引,为了保证 `col3` 在所有分区中的唯一性,`uidx3` 必须为全局索引;`uidx12``idx1` 是基于 `col1` 列的索引,因此可以是全局索引或局部索引。
1773-
1774-
```sql
1775-
ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCAL, uidx3 GLOBAL, idx1 LOCAL);
1776-
```
1777-
1778-
#### 全局索引的限制
1779-
1780-
- 如果索引定义中未显式指定 `GLOBAL` 关键字,TiDB 将默认创建局部索引 (Local Index)。
1781-
- `GLOBAL``LOCAL` 关键字仅适用于分区表,对非分区表没有影响。即在非分区表中,全局索引和局部索引之间没有区别。
1782-
- 以下 DDL 操作会触发全局索引的更新:`DROP PARTITION``TRUNCATE PARTITION``REORGANIZE PARTITION`。这些 DDL 需等待全局索引更新完成后才会返回结果,耗时会相应增加。尤其是在数据归档场景下,如 `DROP PARTITION``TRUNCATE PARTITION`,若没有全局索引,通常可以立即完成;但使用全局索引后,耗时会随着所需更新的索引数量的增加而增加。
1783-
- 包含全局索引的表不支持 `EXCHANGE PARTITION`
1784-
- 默认情况下,分区表的主键为聚簇索引,且必须包含分区键。如果要求主键不包含分区建,可以在建表时显式指定主键为非聚簇的全局索引,例如:`PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`
1785-
- 如果在表达式列上添加了全局索引,或者一个全局索引同时也是前缀索引(如 `UNIQUE KEY idx_id_prefix (id(10)) GLOBAL`),你需要为该全局索引手动收集统计信息。
1689+
关于全局索引的详细介绍,参见[全局索引](/global-indexes.md)
17861690

17871691
### 关于函数的分区限制
17881692

placement-rules-in-sql.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ PARTITION BY RANGE( YEAR(purchased) ) (
295295
);
296296
```
297297

298-
如果没有为表中的某个分区指定任何放置策略,该分区将尝试继承表上可能存在的策略。如果该表有[全局索引](/partitioned-table.md#全局索引),索引将应用与该表相同的放置策略。在上面示例中:
298+
如果没有为表中的某个分区指定任何放置策略,该分区将尝试继承表上可能存在的策略。如果该表有[全局索引](/global-indexes.md),索引将应用与该表相同的放置策略。在上面示例中:
299299

300300
- `p0` 分区将会应用 `storageforhistorydata` 策略
301301
- `p4` 分区将会应用 `storagefornewdata` 策略

releases/release-8.3.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ TiDB 版本:8.3.0
119119

120120
从 v8.3.0 开始,全局索引作为实验特性正式发布。你可通过关键字 `Global` 为分区表显式创建一个全局索引,从而去除分区表唯一建必须包含分区表达式中用到的所有列的限制,满足灵活的业务需求。同时基于全局索引也提升了非分区列的查询性能。
121121

122-
更多信息,请参考[用户文档](/partitioned-table.md#全局索引)
122+
更多信息,请参考[用户文档](/global-indexes.md)
123123

124124
### 稳定性
125125

0 commit comments

Comments
 (0)