Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

partition: global index GA & deprecated tidb_enable_table_partition, tidb_enable_list_partition and tidb_enable_global_index #18659

Merged
merged 12 commits into from
Oct 15, 2024
8 changes: 5 additions & 3 deletions choose-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,17 @@ mysql> SHOW WARNINGS;

#### Skyline-Pruning

Skyline-Pruning 是一个针对索引的启发式过滤规则,能降低错误估算导致选错索引的概率。Skyline-Pruning 从以下三个维度衡量一个索引的优劣
Skyline-Pruning 是一个针对索引的启发式过滤规则,能降低错误估算导致选错索引的概率。Skyline-Pruning 从以下维度衡量一个索引的优劣

- 索引的列涵盖了多少访问条件。“访问条件”指的是可以转化为某列范围的 `where` 条件,如果某个索引的列集合涵盖的访问条件越多,那么它在这个维度上更优。

- 选择该索引读表时,是否需要回表(即该索引生成的计划是 IndexReader 还是 IndexLookupReader)。不用回表的索引在这个维度上优于需要回表的索引。如果均需要回表,则比较索引的列涵盖了多少过滤条件。过滤条件指的是可以根据索引判断的 `where` 条件。如果某个索引的列集合涵盖的访问条件越多,则回表数量越少,那么它在这个维度上越优。

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

对于以上三种维度,如果索引 `idx_a` 在这三个维度上都不比 `idx_b` 差,且有一个维度比 `idx_b` 好,那么 TiDB 会优先选择 `idx_a`。在执行 `EXPLAIN FORMAT = 'verbose' ...` 语句时,如果 Skyline-Pruning 排除了某些索引,TiDB 会输出一条 NOTE 级别的 warning 提示哪些索引在 Skyline-Pruning 排除之后保留下来。
- 该索引是否为[全局索引](/partitioned-table.md#全局索引)。在分区表中,全局索引相比普通索引能有效的降低一个 SQL 的 cop task 数量,进而提升整体性能。

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

在以下示例中,索引 `idx_b` 和 `idx_e` 均劣于 `idx_b_c`,因而被 Skyline-Pruning 排除,`SHOW WARNING` 的返回结果显示了经过 Skyline-Pruning 后剩余的索引。

Expand Down
26 changes: 5 additions & 21 deletions partitioned-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,6 @@ ALTER TABLE table_name LAST PARTITION LESS THAN (<expression>)

### List 分区

在创建 List 分区表之前,请确保以下系统变量为其默认值 `ON`:

- [`tidb_enable_list_partition`](/system-variables.md#tidb_enable_list_partition-从-v50-版本开始引入)
- [`tidb_enable_table_partition`](/system-variables.md#tidb_enable_table_partition)

List 分区和 Range 分区有很多相似的地方。不同之处主要在于 List 分区中,对于表的每个分区中包含的所有行,按分区表达式计算的值属于给定的数据集合。每个分区定义的数据集合有任意个值,但不能有重复的值,可通过 `PARTITION ... VALUES IN (...)` 子句对值进行定义。

假设你要创建一张人事记录表,示例如下:
Expand Down Expand Up @@ -1463,7 +1458,7 @@ SELECT store_id, COUNT(department_id) AS c

> **注意:**
>
> 该规则仅适用于系统变量 [`tidb_enable_global_index`](/system-variables.md#tidb_enable_global_index-从-v760-版本开始引入) 未开启的场景。当开启该变量时,分区表的唯一键可以不包含分区表达式中用到的所有列,详情参考[全局索引](#全局索引)。
> 使用[全局索引](#全局索引)时,可以忽略该规则

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

Expand Down Expand Up @@ -1543,7 +1538,7 @@ PARTITION BY HASH(col1 + col3)
```

```
ERROR 1491 (HY000): A PRIMARY KEY must include all columns in the table's partitioning function
ERROR 8264 (HY000): Global Index is needed for index 'col1', since the unique index is not including all partitioning columns, and GLOBAL is not given as IndexOption
```

原因是 `col1` 和 `col3` 出现在分区键中,但是几个唯一键定义并没有完全包含它们,做如下修改后语句即为合法:
Expand Down Expand Up @@ -1671,7 +1666,7 @@ CREATE TABLE t (a varchar(20), b blob,
```

```sql
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
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
```

#### 全局索引
Expand All @@ -1680,19 +1675,13 @@ ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's parti

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

> **警告:**
>
> 全局索引目前为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

如果你需要创建的唯一索引**不包含分区表达式中使用的所有列**,可以通过启用 [`tidb_enable_global_index`](/system-variables.md#tidb_enable_global_index-从-v760-版本开始引入) 系统变量并在索引定义中添加 `GLOBAL` 关键字来实现。
如果你需要创建的唯一索引**不包含分区表达式中使用的所有列**,可以通过在索引定义中添加 `GLOBAL` 关键字来实现。

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

```sql
SET tidb_enable_global_index = ON;

CREATE TABLE t1 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
Expand All @@ -1710,8 +1699,6 @@ PARTITIONS 4;
请注意,**聚簇索引**不能成为全局索引,如下例所示:

```sql
SET tidb_enable_global_index = ON;

CREATE TABLE t2 (
col1 INT NOT NULL,
col2 DATE NOT NULL,
Expand Down Expand Up @@ -1774,6 +1761,7 @@ ALTER TABLE t1 PARTITION BY HASH (col1) PARTITIONS 3 UPDATE INDEXES (uidx12 LOCA
- `GLOBAL` 和 `LOCAL` 关键字仅适用于分区表,对非分区表没有影响。即在非分区表中,全局索引和局部索引之间没有区别。
- DDL 操作如 `ADD PARTITION`、`DROP PARTITION`、`TRUNCATE PARTITION`、`REORGANIZE PARTITION`、`SPLIT PARTITION` 和 `EXCHANGE PARTITION` 等也会触发对全局索引的更新,这些 DDL 的执行结果将在全局索引更新完成后才会返回。因此,这可能会延迟一些通常需要快速完成的 DDL 的操作,如数据归档操作(`EXCHANGE PARTITION`、`TRUNCATE PARTITION` 和 `DROP PARTITION`)。而如果没有全局索引,这些 DDL 操作可以立即执行完成。
- 默认情况下,分区表的主键为聚簇索引,且必须包含分区键。如果要求主键不包含分区建,可以在建表时显式指定主键为非聚簇的全局索引,例如:`PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`。
- 如果在表达式列上添加了全局索引,或者一个全局索引同时也是前缀索引(如 `UNIQUE KEY idx_id_prefix (id(10)) GLOBAL`),你需要为该全局索引手动收集统计信息。
lilin90 marked this conversation as resolved.
Show resolved Hide resolved

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

Expand Down Expand Up @@ -1905,10 +1893,6 @@ select * from t;
5 rows in set (0.00 sec)
```

环境变量 `tidb_enable_list_partition` 可以控制是否启用分区表功能。如果该变量设置为 `OFF`,则建表时会忽略分区信息,以普通表的方式建表。

该变量仅作用于建表,已经建表之后再修改该变量无效。详见[系统变量和语法](/system-variables.md#tidb_enable_list_partition-从-v50-版本开始引入)。

### 动态裁剪模式

TiDB 访问分区表有两种模式,`dynamic` 和 `static`。从 v6.3.0 开始,默认使用 `dynamic` 模式。但是注意,`dynamic` 模式仅在表级别汇总统计信息(即 GlobalStats)收集完成的情况下生效。如果选择了 `dynamic` 但 GlobalStats 未收集完成,TiDB 会仍采用 `static` 模式。关于 GlobalStats 更多信息,请参考[动态裁剪模式下的分区表统计信息](/statistics.md#收集动态裁剪模式下的分区表统计信息)。
Expand Down
2 changes: 0 additions & 2 deletions placement-rules-in-sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,6 @@ CREATE PLACEMENT POLICY storageforhistorydata CONSTRAINTS="[+node=history]";
CREATE PLACEMENT POLICY storagefornewdata CONSTRAINTS="[+node=new]";
CREATE PLACEMENT POLICY companystandardpolicy CONSTRAINTS="";

SET tidb_enable_global_index = ON;

CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE, UNIQUE INDEX idx(id) GLOBAL)
PLACEMENT POLICY=companystandardpolicy
PARTITION BY RANGE( YEAR(purchased) ) (
Expand Down
15 changes: 4 additions & 11 deletions system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -1935,17 +1935,13 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;

### `tidb_enable_global_index` <span class="version-mark">从 v7.6.0 版本开始引入</span>

> **警告:**
>
> 该变量控制的功能为实验特性,不建议在生产环境中使用。该功能可能会在未事先通知的情况下发生变化或删除。如果发现 bug,请在 GitHub 上提 [issue](https://github.com/pingcap/tidb/issues) 反馈。

- 作用域:SESSION | GLOBAL
- 是否持久化到集群:是
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 类型:布尔型
- 默认值:`OFF`
- 可选值:`OFF`,`ON`
- 默认值:`ON`
- 该变量控制是否支持为分区表创建[全局索引](/partitioned-table.md#全局索引)。启用此变量后,你可以通过在索引定义中添加 `GLOBAL` 选项创建不包含分区表达式中所有列的唯一索引。
- 从 v8.4.0 开始,该变量被废弃。其值将固定为默认值 `ON`,即默认启用[全局索引](/partitioned-table.md#全局索引)。

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

Expand Down Expand Up @@ -2065,6 +2061,7 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;
- 类型:布尔型
- 默认值:`ON`
- 这个变量用来设置是否开启 `LIST (COLUMNS) TABLE PARTITION` 特性。
- 从 v8.4.0 开始,该变量被废弃。其值将固定为默认值 `ON`,即默认启用 [List 分区](/partitioned-table.md#list-分区)。

### `tidb_enable_local_txn`

Expand Down Expand Up @@ -2392,11 +2389,7 @@ Query OK, 0 rows affected (0.09 sec)
- 是否受 Hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value) 控制:否
- 默认值:`ON`
- 类型:枚举型
- 可选值:`OFF`,`ON`,`AUTO`
- 这个变量用来设置是否开启 `TABLE PARTITION` 特性。目前变量支持以下三种值:
- 默认值 `ON` 表示开启 TiDB 当前已实现了的分区表类型,目前 Range partition、Hash partition 以及 Range column 单列的场景会生效。
- `AUTO` 目前作用和 `ON` 一样。
- `OFF` 表示关闭 `TABLE PARTITION` 特性,此时语法还是保持兼容,只是创建的表并不是真正的分区表,而是普通的表。
- 从 v8.4.0 开始,该变量被废弃。其值将固定为默认值 `ON`,即默认启用[分区表](/partitioned-table.md)。

### `tidb_enable_telemetry` <span class="version-mark">从 v4.0.2 版本开始引入</span>

Expand Down