Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions TOC.md
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,7 @@
- [下推到 TiKV 的表达式列表](/functions-and-operators/expressions-pushed-down.md)
- [Oracle 与 TiDB 函数和语法差异对照](/oracle-functions-to-tidb.md)
- [聚簇索引](/clustered-indexes.md)
- [全局索引](/global-indexes.md)
- [向量索引](/vector-search/vector-search-index.md)
- [约束](/constraints.md)
- [生成列](/generated-columns.md)
Expand Down
4 changes: 2 additions & 2 deletions basic-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ aliases: ['/docs-cn/dev/basic-features/','/docs-cn/dev/experimental-features-4.0
| [多值索引](/sql-statements/sql-statement-create-index.md#多值索引) | Y | Y | Y | Y | N | N | N |
| [外键约束](/foreign-key.md) | Y | E | E | E | N | N | N |
| [TiFlash 延迟物化](/tiflash/tiflash-late-materialization.md) | Y | Y | Y | Y | N | N | N |
| [全局索引 (Global Index)](/partitioned-table.md#全局索引) | Y | N | N | N | N | N | N |
| [全局索引 (Global Index)](/global-indexes.md) | Y | N | N | N | N | N | N |
| [向量索引](/vector-search/vector-search-index.md) | E | N | N | N | N | N | N |

## SQL 语句
Expand Down Expand Up @@ -172,7 +172,7 @@ aliases: ['/docs-cn/dev/basic-features/','/docs-cn/dev/experimental-features-4.0
| [Range INTERVAL 分区](/partitioned-table.md#range-interval-分区) | Y | Y | Y | Y | E | N | N |
| [分区表转换为非分区表](/partitioned-table.md#将分区表转换为非分区表) | Y | Y | Y | N | N | N | N |
| [对现有表进行分区](/partitioned-table.md#对现有表进行分区) | Y | Y | Y | N | N | N | N |
| [全局索引 (Global Index)](/partitioned-table.md#全局索引) | Y | N | N | N | N | N | N |
| [全局索引 (Global Index)](/global-indexes.md) | Y | N | N | N | N | N | N |

## 统计信息

Expand Down
2 changes: 1 addition & 1 deletion best-practices/tidb-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通

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

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

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

Expand Down
313 changes: 313 additions & 0 deletions global-indexes.md

Large diffs are not rendered by default.

Binary file added media/global-index-mechanism.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added media/global-index-vs-local-index.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
104 changes: 2 additions & 102 deletions partitioned-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ ALTER TABLE member_level PARTITION BY RANGE(level)
PARTITION pMax VALUES LESS THAN (MAXVALUE));
```

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

```sql
CREATE TABLE t1 (
Expand Down Expand Up @@ -1474,7 +1474,7 @@ SELECT store_id, COUNT(department_id) AS c

> **注意:**
>
> 使用[全局索引](#全局索引)时,可以忽略该规则。
> 使用[全局索引](/global-indexes.md)时,可以忽略该规则。

这里所指的唯一也包含了主键,因为根据主键的定义,主键必须是唯一的。例如,下面这些建表语句就是无效的:

Expand Down Expand Up @@ -1685,106 +1685,6 @@ CREATE TABLE t (a varchar(20), b blob,
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
```

### 全局索引

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

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

如果你需要创建全局索引,可以通过在索引定义中添加 `GLOBAL` 关键字来实现。

> **注意:**
>
> 全局索引对分区管理有影响,执行 `DROP`、`TRUNCATE` 和 `REORGANIZE PARTITION` 操作也会触发表级别全局索引的更新,这意味着这些 DDL 操作只有在对应表的全局索引完全更新后才会返回结果。

```sql
CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
col3 INT NOT NULL,
col4 INT NOT NULL,
UNIQUE KEY uidx12(col1, col2) GLOBAL,
UNIQUE KEY uidx3(col3),
KEY idx1(col1) GLOBAL
)
PARTITION BY HASH(col3)
PARTITIONS 4;
```

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

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

```sql
CREATE TABLE t2 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
PRIMARY KEY (col2) CLUSTERED GLOBAL
) PARTITION BY HASH(col1) PARTITIONS 5;
```

```
ERROR 1503 (HY000): A CLUSTERED INDEX must include all columns in the table's partitioning function
```

聚簇索引不能成为全局索引,是因为如果聚簇索引是全局索引,则表将不再分区。这是因为聚簇索引的键是分区级别的行数据的键,但全局索引是表级别的,这就造成了冲突。如果需要将主键设置为全局索引,则需要显式设置该主键为非聚簇索引,如 `PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`。

你可以通过 [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) 输出中的 `GLOBAL` 索引选项来识别全局索引。

```sql
SHOW CREATE TABLE t1\G
```

```
Table: t1
Create Table: CREATE TABLE `t1` (
`col1` int NOT NULL,
`col2` date NOT NULL,
`col3` int NOT NULL,
`col4` int NOT NULL,
UNIQUE KEY `uidx12` (`col1`,`col2`) /*T![global_index] GLOBAL */,
UNIQUE KEY `uidx3` (`col3`),
KEY `idx1` (`col1`) /*T![global_index] GLOBAL */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin
PARTITION BY HASH (`col3`) PARTITIONS 4
1 row in set (0.00 sec)
```

或查询 [`INFORMATION_SCHEMA.TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) 表并查看输出中的 `IS_GLOBAL` 列来识别全局索引。

```sql
SELECT * FROM information_schema.tidb_indexes WHERE table_name='t1';
```

```
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
| 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 |
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
| test | t1 | 0 | uidx12 | 1 | col1 | NULL | | NULL | 1 | YES | NO | 1 |
| test | t1 | 0 | uidx12 | 2 | col2 | NULL | | NULL | 1 | YES | NO | 1 |
| test | t1 | 0 | uidx3 | 1 | col3 | NULL | | NULL | 2 | YES | NO | 0 |
| test | t1 | 1 | idx1 | 1 | col1 | NULL | | NULL | 3 | YES | NO | 1 |
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
3 rows in set (0.00 sec)
```

在对普通表进行分区或者对分区表进行重新分区时,可以根据需要将索引更新为全局索引或局部索引。

例如,下面的 SQL 语句会基于 `col1` 列对表 `t1` 进行重新分区,并将该表中的全局索引 `uidx12` 和 `idx1` 更新为局部索引,将局部索引 `uidx3` 更新为全局索引。`uidx3` 是基于 `col3` 列的唯一索引,为了保证 `col3` 在所有分区中的唯一性,`uidx3` 必须为全局索引;`uidx12` 和 `idx1` 是基于 `col1` 列的索引,因此可以是全局索引或局部索引。

```sql
ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCAL, uidx3 GLOBAL, idx1 LOCAL);
```

#### 全局索引的限制

- 如果索引定义中未显式指定 `GLOBAL` 关键字,TiDB 将默认创建局部索引 (Local Index)。
- `GLOBAL` 和 `LOCAL` 关键字仅适用于分区表,对非分区表没有影响。即在非分区表中,全局索引和局部索引之间没有区别。
- 以下 DDL 操作会触发全局索引的更新:`DROP PARTITION`、`TRUNCATE PARTITION` 和 `REORGANIZE PARTITION`。这些 DDL 需等待全局索引更新完成后才会返回结果,耗时会相应增加。尤其是在数据归档场景下,如 `DROP PARTITION` 和 `TRUNCATE PARTITION`,若没有全局索引,通常可以立即完成;但使用全局索引后,耗时会随着所需更新的索引数量的增加而增加。
- 包含全局索引的表不支持 `EXCHANGE PARTITION`。
- 默认情况下,分区表的主键为聚簇索引,且必须包含分区键。如果要求主键不包含分区建,可以在建表时显式指定主键为非聚簇的全局索引,例如:`PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`。
- 如果在表达式列上添加了全局索引,或者一个全局索引同时也是前缀索引(如 `UNIQUE KEY idx_id_prefix (id(10)) GLOBAL`),你需要为该全局索引手动收集统计信息。

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

只有以下函数可以用于分区表达式:
Expand Down
2 changes: 1 addition & 1 deletion placement-rules-in-sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ PARTITION BY RANGE( YEAR(purchased) ) (
);
```

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

- `p0` 分区将会应用 `storageforhistorydata` 策略
- `p4` 分区将会应用 `storagefornewdata` 策略
Expand Down
2 changes: 1 addition & 1 deletion releases/release-8.5.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ TiDB 8.5.0 为长期支持版本 (Long-Term Support Release, LTS)。
<td>实例级执行计划缓存允许同一个 TiDB 实例的所有会话共享执行计划缓存。与现有的会话级执行计划缓存相比,实例级执行计划缓存能够在内存中缓存更多执行计划,减少 SQL 编译时间,从而降低 SQL 整体运行时间,提升 OLTP 的性能和吞吐,同时更好地控制内存使用,提升数据库稳定性。</td>
</tr>
<tr>
<td><a href="https://docs.pingcap.com/zh/tidb/v8.5/partitioned-table#全局索引">分区表全局索引</a>(从 v8.4.0 开始成为正式功能)</td>
<td><a href="https://docs.pingcap.com/zh/tidb/v8.5/global-indexes>分区表全局索引</a>(从 v8.4.0 开始成为正式功能)</td>
<td>全局索引可以有效提高检索非分区列的效率,并且消除了唯一键必须包含分区键的限制。该功能扩展了 TiDB 分区表的使用场景,提升了分区表的性能,降低了分区表在一些查询场景的资源消耗。</td>
</tr>
<tr>
Expand Down
2 changes: 1 addition & 1 deletion sql-statements/sql-statement-add-column.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ SELECT * FROM t1;
* 不支持将新添加的列设为 `PRIMARY KEY`。
* 不支持将新添加的列设为 `AUTO_INCREMENT`。
* 对添加生成列有局限性,具体可参考:[生成列局限性](/generated-columns.md#生成列的局限性)。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展,你可以在添加新列时通过将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为 `GLOBAL` 来设置[全局索引](/partitioned-table.md#全局索引)。该扩展与 MySQL 不兼容。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展,你可以在添加新列时通过将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为 `GLOBAL` 来设置[全局索引](/global-indexes.md)。该扩展与 MySQL 不兼容。

## 另请参阅

Expand Down
2 changes: 1 addition & 1 deletion sql-statements/sql-statement-add-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
* TiDB 支持解析 `FULLTEXT` 语法,但不支持使用 `FULLTEXT` 索引。
* 不支持降序索引(类似于 MySQL 5.7)。
* 无法向表中添加 `CLUSTERED` 类型的 `PRIMARY KEY`。要了解关于 `CLUSTERED` 主键的详细信息,请参考[聚簇索引](/clustered-indexes.md)。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为[全局索引](/partitioned-table.md#全局索引)。该扩展与 MySQL 不兼容。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为[全局索引](/global-indexes.md)。该扩展与 MySQL 不兼容。

## 另请参阅

Expand Down
2 changes: 1 addition & 1 deletion sql-statements/sql-statement-create-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ CREATE UNIQUE INDEX c1 ON t1 (c1) INVISIBLE;
* 表达式索引与视图存在兼容性问题。通过视图进行查询时,无法使用上表达式索引。
* 表达式索引与 Binding 存在兼容性问题。当表达式索引中的表达式存在常量时,对应查询所建的 Binding 会扩大范围。假设表达式索引中的表达式为 `a+1`,对应的查询条件为 `a+1 > 2`。则建立的 Binding 为 `a+? > ?`,这会导致像 `a+2 > 2` 这样的查询也会强制使用表达式索引,得到一个较差的执行计划。这同样影响 SQL Plan Management (SPM) 中的捕获和演进功能。
* 多值索引写入的数据必须与定义类型完全匹配,否则数据写入失败。详见[创建多值索引](/sql-statements/sql-statement-create-index.md#创建多值索引)。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `UNIQUE INDEX` 设置为[全局索引](/partitioned-table.md#全局索引)。该扩展与 MySQL 不兼容。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `UNIQUE INDEX` 设置为[全局索引](/global-indexes.md)。该扩展与 MySQL 不兼容。

## 另请参阅

Expand Down
2 changes: 1 addition & 1 deletion sql-statements/sql-statement-create-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ mysql> DESC t1;
* `COMMENT` 属性不支持 `WITH PARSER` 选项。
* TiDB 在单个表中默认支持 1017 列,最大可支持 4096 列。InnoDB 中相应的数量限制为 1017 列,MySQL 中的硬限制为 4096 列。详情参阅 [TiDB 使用限制](/tidb-limitations.md)。
* 分区表支持 `HASH`、`RANGE`、`LIST` 和 `KEY` [分区类型](/partitioned-table.md#分区类型)。对于不支持的分区类型,TiDB 会报 `Warning: Unsupported partition type %s, treat as normal table` 错误,其中 `%s` 为不支持的具体分区类型。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为[全局索引](/partitioned-table.md#全局索引)。该扩展与 MySQL 不兼容。
* TiDB 对[分区表](/partitioned-table.md)进行了扩展。你可以指定 `GLOBAL` 索引选项将 `PRIMARY KEY` 或 `UNIQUE INDEX` 设置为[全局索引](/global-indexes.md)。该扩展与 MySQL 不兼容。

## 另请参阅

Expand Down
4 changes: 2 additions & 2 deletions system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -1971,8 +1971,8 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 类型:布尔型
- 默认值:`ON`
- 该变量控制是否支持为分区表创建[全局索引](/partitioned-table.md#全局索引)。启用此变量后,你可以通过在索引定义中添加 `GLOBAL` 选项创建不包含分区表达式中所有列的唯一索引。
- 从 v8.4.0 开始,该变量被废弃。其值将固定为默认值 `ON`,即默认启用[全局索引](/partitioned-table.md#全局索引)。
- 该变量控制是否支持为分区表创建[全局索引](/global-indexes.md)。启用此变量后,你可以通过在索引定义中添加 `GLOBAL` 选项创建不包含分区表达式中所有列的唯一索引。
- 从 v8.4.0 开始,该变量被废弃。其值将固定为默认值 `ON`,即默认启用[全局索引](/global-indexes.md)。

### `tidb_enable_lazy_cursor_fetch` <span class="version-mark">从 v8.3.0 版本开始引入</span>

Expand Down
Loading