From 5059c83a096bae8f0c8b3046a6849b28317a0609 Mon Sep 17 00:00:00 2001 From: tangenta Date: Mon, 24 Feb 2020 17:58:08 +0800 Subject: [PATCH] reference: add user documentation for auto_random feature (#2209) --- TOC.md | 2 + reference/best-practices/high-concurrency.md | 12 +- .../tidb-server/configuration-file.md | 10 ++ reference/sql/attributes/auto-random.md | 103 ++++++++++++++++++ .../sql/language-structure/comment-syntax.md | 2 +- .../keywords-and-reserved-words.md | 1 + reference/sql/statements/create-table.md | 3 +- 7 files changed, 129 insertions(+), 4 deletions(-) create mode 100644 reference/sql/attributes/auto-random.md diff --git a/TOC.md b/TOC.md index 013f601a2131..e3e95c428331 100644 --- a/TOC.md +++ b/TOC.md @@ -81,6 +81,8 @@ - [用户自定义变量](/reference/sql/language-structure/user-defined-variables.md) - [表达式语法](/reference/sql/language-structure/expression-syntax.md) - [注释语法](/reference/sql/language-structure/comment-syntax.md) + + 表属性和列属性 + - [`AUTO_RANDOM`](/reference/sql/attributes/auto-random.md) + 数据类型 - [概述](/reference/sql/data-types/overview.md) - [默认值](/reference/sql/data-types/default-values.md) diff --git a/reference/best-practices/high-concurrency.md b/reference/best-practices/high-concurrency.md index 243664c1d4e8..fb64b5f7a41b 100644 --- a/reference/best-practices/high-concurrency.md +++ b/reference/best-practices/high-concurrency.md @@ -124,7 +124,7 @@ SPLIT TABLE table_name [INDEX index_name] BY (value_list) [, (value_list)] ![Table Region Range](/media/best-practices/table-Region-range.png) -从上图可知,根据行数据 key 的编码规则,行 ID (rowID) 是行数据中唯一可变的部分。在 TiDB 中,rowID 是一个 Int64 整形。但是用户不一定能将 Int64 整形范围均匀切分成需要的份数,然后均匀分布在不同的节点上,还需要结合实际情况。 +从上图可知,根据行数据 key 的编码规则,行 ID (rowID) 是行数据中唯一可变的部分。在 TiDB 中,rowID 是一个 Int64 整型。但是用户不一定能将 Int64 整型范围均匀切分成需要的份数,然后均匀分布在不同的节点上,还需要结合实际情况。 如果行 ID 的写入是完全离散的,那么上述方式是可行的。如果行 ID 或者索引有固定的范围或者前缀(例如,只在 `[2000w, 5000w)` 的范围内离散插入数据),这种写入依然在业务上不产生热点,但是如果按上面的方式进行切分,那么有可能一开始数据仍只写入到某个 Region 上。 @@ -170,7 +170,9 @@ SPLIT TABLE TEST_HOTSPOT BETWEEN (0) AND (9223372036854775807) REGIONS 128; ### 更复杂的热点问题 -如果表没有主键或者主键不是 Int 类型,而且用户也不想自己生成一个随机分布的主键 ID 的话,TiDB 内部有一个隐式的 `_tidb_rowid` 列作为行 ID。在不使用 `SHARD_ROW_ID_BITS` 的情况下,`_tidb_rowid` 列的值基本也为单调递增,此时也会有写热点存在(参阅 [`SHARD_ROW_ID_BITS` 的详细说明](/reference/configuration/tidb-server/tidb-specific-variables.md#shard_row_id_bits))。 +**问题一:** + +如果表没有主键或者主键不是整数类型,而且用户也不想自己生成一个随机分布的主键 ID 的话,TiDB 内部有一个隐式的 `_tidb_rowid` 列作为行 ID。在不使用 `SHARD_ROW_ID_BITS` 的情况下,`_tidb_rowid` 列的值基本也为单调递增,此时也会有写热点存在(参阅 [`SHARD_ROW_ID_BITS` 的详细说明](/reference/configuration/tidb-server/tidb-specific-variables.md#shard_row_id_bits))。 要避免由 `_tidb_rowid` 带来的写入热点问题,可以在建表时,使用 `SHARD_ROW_ID_BITS` 和 `PRE_SPLIT_REGIONS` 这两个建表选项(参阅 [`PRE_SPLIT_REGIONS` 的详细说明](/reference/sql/statements/split-region.md#pre_split_regions))。 @@ -193,6 +195,12 @@ create table t (a int, b int) shard_row_id_bits = 4 pre_split_regions=·3; 开始写数据进表 t 后,数据会被写入提前切分好的 8 个 Region 中,这样也避免了刚开始建表完后因为只有一个 Region 而存在的写热点问题。 +**问题二:** + +如果表的主键为整数类型,并且该表使用了 `AUTO_INCREMENT` 来保证主键唯一性(不需要连续或递增)的表而言,由于 TiDB 直接使用主键行值作为 `_tidb_rowid`,此时无法使用 `SHARD_ROW_ID_BITS` 来打散热点。 + +要解决上述热点问题,可以利用 `AUTO_RANDOM` 列属性(参阅 [`AUTO_RANDOM` 的详细说明](/reference/sql/attributes/auto-random.md)),将 `AUTO_INCREMENT` 改为 `AUTO_RANDOM`,插入数据时让 TiDB 自动为整型主键列分配一个值,消除行 ID 的连续性,从而达到打散热点的目的。 + ## 参数配置 TiDB 2.1 版本中在 SQL 层引入了 [latch 机制](/reference/configuration/tidb-server/configuration-file.md#txn-local-latches),用于在写入冲突比较频繁的场景中提前发现事务冲突,减少 TiDB 和 TiKV 事务提交时写写冲突导致的重试。通常,跑批场景使用的是存量数据,所以并不存在事务的写入冲突。可以把 TiDB 的 latch 功能关闭,以减少为细小对象分配内存: diff --git a/reference/configuration/tidb-server/configuration-file.md b/reference/configuration/tidb-server/configuration-file.md index 57f9c818577b..d17a809559ee 100644 --- a/reference/configuration/tidb-server/configuration-file.md +++ b/reference/configuration/tidb-server/configuration-file.md @@ -448,3 +448,13 @@ TiDB 服务状态相关配置。 + 悲观事务中每个语句最大重试次数,超出该限制将会报错。 + 默认值:256 + +## experimental + +experimental 部分为 TiDB 实验功能相关的配置。该部分从 v3.1.0 开始引入。 + +### `allow-auto-random` 从 v3.1.0 版本开始引入 + ++ 用于控制是否允许使用 `AUTO_RANDOM`。 ++ 默认值:false ++ 默认情况下,不支持使用 `AUTO_RANDOM`。当该值为 true 时,不允许同时设置 alter-primary-key 为 true。 diff --git a/reference/sql/attributes/auto-random.md b/reference/sql/attributes/auto-random.md new file mode 100644 index 000000000000..61340211cc1d --- /dev/null +++ b/reference/sql/attributes/auto-random.md @@ -0,0 +1,103 @@ +--- +title: AUTO_RANDOM +category: reference +--- + +# AUTO_RANDOM 从 v3.1.0 版本开始引入 + +> **警告:** +> +> 当前 `AUTO_RANDOM` 属性为实验功能,**不建议在生产环境中使用**。在后续版本中,`AUTO_RANDOM` 的语法或语义可能会变化。 + +使用 `AUTO_RANDOM` 功能前,须在 TiDB 配置文件 `experimental` 部分设置 `allow-auto-random = true`。该参数详情可参见 [`allow-auto-random`](/reference/configuration/tidb-server/configuration-file.md#allow-auto-random)。 + +## 使用场景 + +`AUTO_RANDOM` 用于解决大批量写数据入 TiDB 时因含有**整型自增主键列**的表而产生的热点问题。详情参阅 [TiDB 高并发写入场景最佳实践](/reference/best-practices/high-concurrency.md)。 + +以下面语句建立的表为例: + +```sql +create table t (a int primary key auto_increment, b varchar(255)) +``` + +在以上语句所建的表上执行大量未指定主键值的 `INSERT` 语句时,示例如下: + +```sql +insert into t(b) values ('a'), ('b'), ('c') +``` + +在该情况下,由于未指定主键列的值(`a` 列),TiDB 会使用连续自增的行值作为行 ID,可能导致单个 TiKV 节点上产生写入热点,进而影响对外提供服务的性能。要避免这种性能下降,可以在执行建表语句时为 `a` 列指定 `AUTO_RANDOM` 属性而不是 `AUTO_INCREMENT` 属性。示例如下: + +{{< copyable "sql" >}} + +```sql +create table t (a int primary key auto_random, b varchar(255)) +``` + +或者 + +{{< copyable "sql" >}} + +```sql +create table t (a int auto_random, b varchar(255), primary key (a)) +``` + +此时再执行形如 `INSERT INTO t(b) values...` 的 `INSERT` 语句, + ++ 如果该 `INSERT` 语句没有指定整型主键列(`a` 列)的值,TiDB 会为该列自动分配值。该值不保证自增,不保证连续,只保证唯一,避免了连续的行 ID 带来的热点问题。 ++ 如果该 `INSERT` 语句显式指定了整型主键列的值,和 `AUTO_INCREMENT` 属性类似,TiDB 会原封不动地保存该值。 + +自动分配值的计算方式如下: + +该行值在二进制形式下的最高 5 位(称为 shard bits)由当前事务的开始时间决定,剩下的位数按照自增的顺序分配。 + +如果希望使用一个不同的 shard bits 的数量,可以在 `AUTO_RANDOM` 后面加一对括号,并在括号中指定,例如: + +{{< copyable "sql" >}} + +```sql +create table t (a int primary key auto_random(3), b varchar(255)) +``` + +以上建表语句中,shard bits 的数量为 `3`。shard bits 的数量的取值范围是 `[1, field_max_bits)`,其中 `field_max_bits` 为整型主键列类型占用的位长度。 + +含有 `AUTO_RANDOM` 属性的表在 `information_schema.tables` 中 `TIDB_ROW_ID_SHARDING_INFO` 一列的值为 `PK_AUTO_RANDOM_BITS=x`,其中 `x` 为 shard bits 的数量。 + +## 兼容性 + +TiDB 支持解析版本注释语法。示例如下: + +{{< copyable "sql" >}} + +```sql +create table t (a int primary key /*T!30100 auto_random */) +``` + +{{< copyable "sql" >}} + +```sql +create table t (a int primary key auto_random) +``` + +以上两个语句含义相同。 + +在 `show create table` 的结果中,`AUTO_RANDOM` 属性会被注释掉。注释会附带一个版本号,例如 `/*T!30100 auto_random */`。其中 `30100` 表示 v3.1.0 引入该功能,低版本的 TiDB 能够忽略带有上述注释的 `AUTO_RANDOM` 属性。 + +该功能支持向前兼容,即降级兼容。v3.1.0 以前的 TiDB 会忽略表(带有上述注释)的 `AUTO_RANDOM` 属性,因此能够使用含有该属性的表。 + +## 使用限制 + +目前在 TiDB 中使用 `AUTO_RANDOM` 有以下限制: + +- 该属性必须指定在整数类型的主键列上,否则会报错。例外情况见[关于 `alter-primary-key` 配置项的说明](#关于-alter-primary-key-配置项的说明)。 +- 不支持使用 `ALTER TABLE` 来修改 `AUTO_RANDOM` 属性,包括添加或移除该属性。 +- 不支持修改含有 `AUTO_RANDOM` 属性的主键列的列类型。 +- 不支持与 `AUTO_INCREMENT` 同时指定在同一列上。 +- 不支持与列的默认值 `DEFAULT` 同时指定在同一列上。 +- 插入数据时,不建议自行显式指定含有 `AUTO_RANDOM` 列的值。不恰当地显式赋值,可能会导致该表提前耗尽用于自动分配的数值。因为用于保证唯一性的 rebase 仅针对除 shard bits 以外的位进行。 + +### 关于 `alter-primary-key` 配置项的说明 + +- 当 `alter-primary-key = true` 时,即使是整型主键列,也不支持使用 `AUTO_RANDOM`。 +- 配置文件中的 `alter-primary-key` 和 `allow-auto-random` 两个配置项的值不允许同时为 `true`。 diff --git a/reference/sql/language-structure/comment-syntax.md b/reference/sql/language-structure/comment-syntax.md index 05a8010fcb68..ad009e210ad5 100644 --- a/reference/sql/language-structure/comment-syntax.md +++ b/reference/sql/language-structure/comment-syntax.md @@ -107,7 +107,7 @@ TiDB 也跟 MySQL 保持一致,支持一种 C 风格注释的变体: 在 TiDB 中,这种写法等价于 `SELECT STRAIGHT_JOIN col1 FROM table1,table2 WHERE ...` -如果注释中指定了 Server 版本号,例如 `/*!50110 KEY_BLOCK_SIZE=1024 */`,在 MySQL 中表示只有 MySQL 的版本大于等于 5.1.10 才会处理这个 comment 中的内容。但是在 TiDB 中,这个版本号不会起作用,所有的 comment 都会处理。 +如果注释中指定了 Server 版本号,例如 `/*!50110 KEY_BLOCK_SIZE=1024 */`,在 MySQL 中表示只有 MySQL 的版本大于等于 5.1.10 才会处理这个 comment 中的内容。但是在 TiDB 中,这个 MySQL 版本号不会起作用,所有的 comment 都被会处理。TiDB 有自己的版本号注释语法,格式为 `/*T!30100 XXX */`。 还有一种注释会被当做是优化器 Hint 特殊对待: diff --git a/reference/sql/language-structure/keywords-and-reserved-words.md b/reference/sql/language-structure/keywords-and-reserved-words.md index f1a5b2362004..ae52958eadb2 100644 --- a/reference/sql/language-structure/keywords-and-reserved-words.md +++ b/reference/sql/language-structure/keywords-and-reserved-words.md @@ -72,6 +72,7 @@ Query OK, 0 rows affected (0.08 sec) - ASC (R) - ASCII - AUTO_INCREMENT +- AUTO_RANDOM - AVG - AVG_ROW_LENGTH diff --git a/reference/sql/statements/create-table.md b/reference/sql/statements/create-table.md index 2ead05fe3523..d45b0ab5d397 100644 --- a/reference/sql/statements/create-table.md +++ b/reference/sql/statements/create-table.md @@ -100,7 +100,8 @@ create_definition: ```sql column_definition: data_type [NOT NULL | NULL] [DEFAULT default_value] - [AUTO_INCREMENT] [UNIQUE [KEY] | [PRIMARY] KEY] + [AUTO_INCREMENT | AUTO_RANDOM [(length)]] + [UNIQUE [KEY] | [PRIMARY] KEY] [COMMENT 'string'] [reference_definition] | data_type [GENERATED ALWAYS] AS (expression)