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: add doc for global index, also with GLOBAL IndexOption/ColumnOption #18543

Merged
merged 29 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fc3ce38
partition: support global index
Defined2014 Jun 20, 2024
3cbe2e5
Update partitioned-table.md
Defined2014 Jun 21, 2024
db1ebf2
Update partitioned-table.md
Defined2014 Jun 21, 2024
b1e96dc
Apply suggestions from code review
Defined2014 Jun 21, 2024
5ed9b56
update
Defined2014 Jun 21, 2024
6e2a908
Apply suggestions from code review
Defined2014 Jul 5, 2024
3997a3c
Apply suggestions from code review
Defined2014 Jul 5, 2024
5c189ac
add placement rules
Defined2014 Jul 9, 2024
791deee
update
Defined2014 Jul 9, 2024
a5729ca
update
Defined2014 Jul 9, 2024
6004f5e
Apply suggestions from code review
hfxsd Jul 31, 2024
c4842dc
Update placement-rules-in-sql.md
hfxsd Aug 1, 2024
58aa8a2
Update system-variables.md
hfxsd Aug 6, 2024
e2bf9e4
Updated with explicit GLOBAL attribute for global indexes
mjonss Aug 8, 2024
456b9d8
Updated unique index limitation for global index
mjonss Aug 12, 2024
49ac459
Linting
mjonss Aug 12, 2024
19b5dac
Update partitioned-table.md
mjonss Aug 13, 2024
c963bc0
Update system-variables.md
mjonss Aug 13, 2024
e42379d
Update sql-statements/sql-statement-add-column.md
mjonss Aug 13, 2024
793a8a2
Update sql-statements/sql-statement-add-index.md
mjonss Aug 13, 2024
ea2de60
Update sql-statements/sql-statement-create-index.md
mjonss Aug 13, 2024
1ed6f43
Update sql-statements/sql-statement-create-table.md
mjonss Aug 13, 2024
331c6a3
Apply suggestions from code review
hfxsd Aug 14, 2024
d488757
Update partitioned-table.md
hfxsd Aug 14, 2024
675cd08
Update partitioned-table.md
hfxsd Aug 14, 2024
c7612a5
add a note to the limitation
hfxsd Aug 15, 2024
43c0610
Apply suggestions from code review
hfxsd Aug 15, 2024
570e8e2
Update partitioned-table.md
hfxsd Aug 15, 2024
6870196
Apply suggestions from code review
hfxsd Aug 19, 2024
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
107 changes: 106 additions & 1 deletion partitioned-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,11 @@ This section introduces some restrictions and limitations on partitioned tables

### Partitioning keys, primary keys and unique keys

This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: **Every unique key on the table must use every column in the table's partitioning expression**. This also includes the table's primary key, because it is by definition a unique key.
This section discusses the relationship of partitioning keys with primary keys and unique keys. The rule governing this relationship can be expressed as follows: **Every unique key on the table must use every column in the table's partitioning expression**. This also includes the table's primary key, because it is by definition a unique key.

> **Note:**
>
> This rule only applies to the scenarios where the [`tidb_enable_global_index`](/system-variables.md#tidb_enable_global_index-new-in-v760) system variable is not enabled. When it is enabled, unique keys in partitioned tables are not required to include all the columns used in the partition expressions. For more information, see [global indexes](#global-indexes).

For example, the following table creation statements are invalid:

Expand Down Expand Up @@ -1662,6 +1666,107 @@ CREATE TABLE t (a varchar(20), b blob,
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
```

hfxsd marked this conversation as resolved.
Show resolved Hide resolved
#### Global indexes

hfxsd marked this conversation as resolved.
Show resolved Hide resolved
Before the introduction of global indexes, TiDB created a local index for each partition, leading to [a limitation](#partitioning-keys-primary-keys-and-unique-keys) that primary keys and unique keys had to include the partition key to ensure data uniqueness. Additionally, when querying data across multiple partitions, TiDB needed to scan the data of each partition to return results.

To address these issues, TiDB introduces the global indexes feature in v8.3.0. A global index covers the data of the entire table with a single index, allowing primary keys and unique keys to maintain global uniqueness without including all partition keys. Moreover, global indexes can access data across multiple partitions in a single operation, significantly improving query performance for non-partitioned keys.

> **Warning:**
>
> The global indexes feature is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub.

qiancai marked this conversation as resolved.
Show resolved Hide resolved
hfxsd marked this conversation as resolved.
Show resolved Hide resolved
To create a global index for a primary key or unique key that **does not include all the columns used in the partition expressions**, you can enable the [`tidb_enable_global_index`](/system-variables.md#tidb_enable_global_index-new-in-v760) system variable and add the `GLOBAL` keyword in the index definition.

> **Note:**
>
> Global indexes affect partition management. `DROP`, `TRUNCATE`, and `REORGANIZE PARTITION` operations also trigger updates to table-level global indexes, meaning that these DDL operations will only return results after the global indexes of the corresponding tables are fully updated.

hfxsd marked this conversation as resolved.
Show resolved Hide resolved
```sql
SET tidb_enable_global_index = ON;

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)
)
PARTITION BY HASH(col3)
PARTITIONS 4;
```

In the preceding example, the unique index `uidx12` is a global index, while `uidx3` is a regular unique index.

Note that a **clustered index** cannot be a global index, as shown in the following example:

```sql
SET tidb_enable_global_index = ON;

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
```

The reason is that if the clustered index is a global index, the table will no longer be partitioned. This is because the key of the clustered index is also the record key at the partition level, but the global index is at the table level, which causes a conflict. If you need to set the primary key as a global index, you must explicitly define it as a non-clustered index, for example, `PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`.

You can identify a global index by the `GLOBAL` index option in the [`SHOW CREATE TABLE`](/sql-statements/sql-statement-show-create-table.md) output.

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

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

Alternatively, you can query the [`INFORMATION_SCHEMA.TIDB_INDEXES`](/information-schema/information-schema-tidb-indexes.md) table and check the `IS_GLOBAL` column in the output.

```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 |
+--------------+------------+------------+----------+--------------+-------------+----------+---------------+------------+----------+------------+-----------+-----------+
3 rows in set (0.00 sec)
```

When partitioning a non-partitioned table or repartitioning an already partitioned table, you can update the indexes to be global indexes or revert them to local indexes as needed:

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

hfxsd marked this conversation as resolved.
Show resolved Hide resolved
##### Limitations of global indexes
hfxsd marked this conversation as resolved.
Show resolved Hide resolved

- If the `GLOBAL` keyword is not explicitly specified in the index definition, TiDB creates a local index by default.
- The `GLOBAL` and `LOCAL` keywords only apply to partitioned tables and do not affect non-partitioned tables. In other words, there is no difference between a global index and a local index in non-partitioned tables.
- DDL operations such as `ADD PARTITION`, `DROP PARTITION`, `TRUNCATE PARTITION`, `REORGANIZE PARTITION`, `SPLIT PARTITION`, and `EXCHANGE PARTITION` also trigger updates to global indexes. The results of these DDL operations will only be returned after the global indexes of the corresponding tables are fully updated. This can delay operations that usually require quick DDL completion, such as data archiving operations (`EXCHANGE PARTITION`, `TRUNCATE PARTITION`, and `DROP PARTITION`). In contrast, when global indexes are not involved, these DDL operations can be completed immediately.
- By default, the primary key of a partitioned table is a clustered index and must include the partition key. If you require the primary key to exclude the partition key, you can explicitly specify the primary key as a non-clustered global index when creating the table, for example, `PRIMARY KEY(col1, col2) NONCLUSTERED GLOBAL`.

### Partitioning limitations relating to functions

Only the functions shown in the following list are allowed in partitioning expressions:
Expand Down
19 changes: 11 additions & 8 deletions placement-rules-in-sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,32 +297,35 @@ ALTER TABLE t PLACEMENT POLICY=default; -- Removes the placement policy 'five_re
You can also specify a placement policy for a partitioned table or a partition. For example:

```sql
CREATE PLACEMENT POLICY storageforhisotrydata CONSTRAINTS="[+node=history]";
CREATE PLACEMENT POLICY storageforhistorydata CONSTRAINTS="[+node=history]";
CREATE PLACEMENT POLICY storagefornewdata CONSTRAINTS="[+node=new]";
CREATE PLACEMENT POLICY companystandardpolicy CONSTRAINTS="";

CREATE TABLE t1 (id INT, name VARCHAR(50), purchased DATE)
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) ) (
PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY=storageforhisotrydata,
PARTITION p0 VALUES LESS THAN (2000) PLACEMENT POLICY=storageforhistorydata,
PARTITION p1 VALUES LESS THAN (2005),
PARTITION p2 VALUES LESS THAN (2010),
PARTITION p3 VALUES LESS THAN (2015),
PARTITION p4 VALUES LESS THAN MAXVALUE PLACEMENT POLICY=storagefornewdata
);
```

If no placement policy is specified for a partition in a table, the partition attempts to inherit the policy (if any) from the table. In the preceding example:
If no placement policy is specified for a partition in a table, the partition attempts to inherit the policy (if any) from the table. If the table has a [global index](/partitioned-table.md#global-indexes), the index will apply the same placement policy as the table. In the preceding example:

- The `p0` partition will apply the `storageforhisotrydata` policy.
- The `p0` partition will apply the `storageforhistorydata` policy.
- The `p4` partition will apply the `storagefornewdata` policy.
- The `p1`, `p2`, and `p3` partitions will apply the `companystandardpolicy` placement policy inherited from the table `t1`.
- If no placement policy is specified for the table `t1`, the `p1`, `p2`, and `p3` partitions will inherit the database default policy or the global default policy.
- The global index `idx` will apply the same `companystandardpolicy` placement policy as the table `t1`.
- If no placement policy is specified for the table `t1`, then the `p1`, `p2`, and `p3` partitions and the global index `idx` will inherit the database default policy or the global default policy.

After placement policies are attached to these partitions, you can change the placement policy for a specific partition as in the following example:

```sql
ALTER TABLE t1 PARTITION p1 PLACEMENT POLICY=storageforhisotrydata;
ALTER TABLE t1 PARTITION p1 PLACEMENT POLICY=storageforhistorydata;
```

## High availability examples
Expand Down Expand Up @@ -479,4 +482,4 @@ After executing the statements in the example, TiDB will place the `app_order` d
| TiDB Lightning | Not compatible yet | An error is reported when TiDB Lightning imports backup data that contains placement policies |
| TiCDC | 6.0 | Ignores placement policies, and does not replicate the policies to the downstream |

</CustomContent>
</CustomContent>
5 changes: 3 additions & 2 deletions sql-statements/sql-statement-add-column.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ ColumnType
ColumnOption
::= 'NOT'? 'NULL'
| 'AUTO_INCREMENT'
| 'PRIMARY'? 'KEY' ( 'CLUSTERED' | 'NONCLUSTERED' )?
| 'UNIQUE' 'KEY'?
| 'PRIMARY'? 'KEY' ( 'CLUSTERED' | 'NONCLUSTERED' )? ( 'GLOBAL' | 'LOCAL' )?
| 'UNIQUE' 'KEY'? ( 'GLOBAL' | 'LOCAL' )?
| 'DEFAULT' ( NowSymOptionFraction | SignedLiteral | NextValueForSequence )
| 'SERIAL' 'DEFAULT' 'VALUE'
| 'ON' 'UPDATE' NowSymOptionFraction
Expand Down Expand Up @@ -89,6 +89,7 @@ mysql> SELECT * FROM t1;
* Adding a new column and setting it to the `PRIMARY KEY` is not supported.
* Adding a new column and setting it to `AUTO_INCREMENT` is not supported.
* There are limitations on adding generated columns, refer to: [generated column limitations](/generated-columns.md#limitations).
* Setting a [global index](/partitioned-table.md#global-indexes) by specifying `PRIMARY KEY` or `UNIQUE INDEX` as `GLOBAL` when you add a new column is a TiDB extension for [partitioned tables](/partitioned-table.md) and is not compatible with MySQL.

## See also

Expand Down
3 changes: 3 additions & 0 deletions sql-statements/sql-statement-add-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ IndexOption
| 'COMMENT' stringLit
| 'VISIBLE'
| 'INVISIBLE'
| 'GLOBAL'
| 'LOCAL'

IndexType
::= 'BTREE'
Expand Down Expand Up @@ -90,6 +92,7 @@ mysql> EXPLAIN SELECT * FROM t1 WHERE c1 = 3;
* TiDB supports parsing the `FULLTEXT` syntax but does not support using the `FULLTEXT` indexes.
* Descending indexes are not supported (similar to MySQL 5.7).
* Adding the primary key of the `CLUSTERED` type to a table is not supported. For more details about the primary key of the `CLUSTERED` type, refer to [clustered index](/clustered-indexes.md).
* Setting a `PRIMARY KEY` or `UNIQUE INDEX` as a [global index](/partitioned-table.md#global-indexes) with the `GLOBAL` index option is a TiDB extension for [partitioned tables](/partitioned-table.md) and is not compatible with MySQL.

## See also

Expand Down
2 changes: 2 additions & 0 deletions sql-statements/sql-statement-create-index.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ IndexOption ::=
| 'WITH' 'PARSER' Identifier
| 'COMMENT' stringLit
| ("VISIBLE" | "INVISIBLE")
| ("GLOBAL" | "LOCAL")

IndexTypeName ::=
'BTREE'
Expand Down Expand Up @@ -356,6 +357,7 @@ The system variables associated with the `CREATE INDEX` statement are `tidb_ddl_
* Expression indexes are incompatible with views. When a query is executed using a view, the expression index cannot be used at the same time.
* Expression indexes have compatibility issues with bindings. When the expression of an expression index has a constant, the binding created for the corresponding query expands its scope. For example, suppose that the expression in the expression index is `a+1`, and the corresponding query condition is `a+1 > 2`. In this case, the created binding is `a+? > ?`, which means that the query with the condition such as `a+2 > 2` is also forced to use the expression index and results in a poor execution plan. In addition, this also affects the baseline capturing and baseline evolution in SQL Plan Management (SPM).
* The data written with multi-valued indexes must exactly match the defined data type. Otherwise, data writes fail. For details, see [create multi-valued indexes](/sql-statements/sql-statement-create-index.md#create-multi-valued-indexes).
* Setting a `UNIQUE KEY` as a [global index](/partitioned-table.md#global-indexes) with the `GLOBAL` index option is a TiDB extension for [partitioned tables](/partitioned-table.md) and is not compatible with MySQL.

## See also

Expand Down
6 changes: 4 additions & 2 deletions sql-statements/sql-statement-create-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ ColumnOptionList ::=
ColumnOption ::=
'NOT'? 'NULL'
| 'AUTO_INCREMENT'
| PrimaryOpt 'KEY'
| 'UNIQUE' 'KEY'?
| PrimaryOpt 'KEY' ( 'GLOBAL' | 'LOCAL' )?
| 'UNIQUE' 'KEY'? ( 'GLOBAL' | 'LOCAL' )?
| 'DEFAULT' DefaultValueExpr
| 'SERIAL' 'DEFAULT' 'VALUE'
| 'ON' 'UPDATE' NowSymOptionFraction
Expand Down Expand Up @@ -77,6 +77,7 @@ IndexOption ::=
'COMMENT' String
| ( 'VISIBLE' | 'INVISIBLE' )
| ('USING' | 'TYPE') ('BTREE' | 'RTREE' | 'HASH')
| ( 'GLOBAL' | 'LOCAL' )

ForeignKeyDef
::= ( 'CONSTRAINT' Identifier )? 'FOREIGN' 'KEY'
Expand Down Expand Up @@ -242,6 +243,7 @@ mysql> DESC t1;
* All of the data types except spatial types are supported.
* TiDB accepts index types such as `HASH`, `BTREE` and `RTREE` in syntax for compatibility with MySQL, but ignores them.
* TiDB supports parsing the `FULLTEXT` syntax but does not support using the `FULLTEXT` indexes.
* Setting a `PRIMARY KEY` or `UNIQUE INDEX` as a [global index](/partitioned-table.md#global-indexes) with the `GLOBAL` index option is a TiDB extension for [partitioned tables](/partitioned-table.md) and is not compatible with MySQL.

<CustomContent platform="tidb">

Expand Down
6 changes: 5 additions & 1 deletion system-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -2128,13 +2128,17 @@ mysql> SELECT job_info FROM mysql.analyze_jobs ORDER BY end_time DESC LIMIT 1;

### tidb_enable_global_index <span class="version-mark">New in v7.6.0</span>

> **Warning:**
>
> The feature controlled by this variable is experimental. It is not recommended that you use it in the production environment. This feature might be changed or removed without prior notice. If you find a bug, you can report an [issue](https://github.com/pingcap/tidb/issues) on GitHub.

- Scope: SESSION | GLOBAL
- Persists to cluster: Yes
- Applies to hint [SET_VAR](/optimizer-hints.md#set_varvar_namevar_value): No
- Type: Boolean
- Default value: `OFF`
- Possible values: `OFF`, `ON`
- This variable controls whether to support creating `Global indexes` for partitioned tables. `Global index` is currently in the development stage. **It is not recommended to modify the value of this system variable**.
- This variable controls whether to support creating [global indexes](/partitioned-table.md#global-indexes) for partitioned tables. When this variable is enabled, TiDB allows you to create unique indexes that **do not include all the columns used in the partition expressions** by specifying `GLOBAL` in the index definition.

### tidb_enable_non_prepared_plan_cache

Expand Down
Loading