Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 5 additions & 5 deletions blacklist-control-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ category: performance
|**优化规则**|**规则名称**|**简介**|
Copy link
Member Author

@lilin90 lilin90 Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ran-huang FYI. The file name of the EN version is blocklist-control-plan.md, added in pingcap/docs#3043. I think we can keep the current Chinese file name now, because it's consistent with words in the body.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Thanks!

| :--- | :--- | :--- |
| 列裁剪 | column_prune | 对于上层算子不需要的列,不在下层算子输出该列,减少计算 |
| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggression 计算 |
| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggregation 计算 |
| 聚合消除 | aggregation_eliminate | 尝试消除执行计划中的某些不必要的聚合算子 |
| 投影消除 | projection_eliminate | 消除执行计划中不必要的投影算子 |
| 最大最小消除 | max_min_eliminate | 改写聚合中的 max/min 计算,转化为 `order by` + `limit 1` |
Expand Down Expand Up @@ -63,7 +63,7 @@ category: performance
{{< copyable "sql" >}}

```sql
delete from mysql.opt_rule_blacklist where name in ("join_reoder", "topn_push_down");
delete from mysql.opt_rule_blacklist where name in ("join_reorder", "topn_push_down");
admin reload opt_rule_blacklist;
```

Expand All @@ -79,7 +79,7 @@ category: performance
| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | <, <=, =, != (`<>`), >, >=, [`<=>`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal-to), [`IN()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_in), IS NULL, LIKE, IS TRUE, IS FALSE, [`COALESCE()`](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#function_coalesce) |
| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | +, -, *, /, [`ABS()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_abs), [`CEIL()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceil), [`CEILING()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_ceiling), [`FLOOR()`](https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_floor) |
| [控制流运算](/functions-and-operators/control-flow-functions.md) | [`CASE`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#operator_case), [`IF()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_if), [`IFNULL()`](https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_ifnull) |
| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)][json_type],<br/> [JSON_EXTRACT(json_doc, path[, path] ...)][json_extract],<br/> [JSON_UNQUOTE(json_val)][json_unquote],<br/> [JSON_OBJECT(key, val[, key, val] ...)][json_object],<br/> [JSON_ARRAY([val[, val] ...])][json_array],<br/> [JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge],<br/> [JSON_SET(json_doc, path, val[, path, val] ...)][json_set],<br/> [JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert],<br/> [JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace],<br/> [JSON_REMOVE(json_doc, path[, path] ...)][json_remove] |
| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_TYPE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-attribute-functions.html#function_json-type),<br/> [JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract),<br/> [JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote),<br/> [JSON_OBJECT(key, val[, key, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object),<br/> [JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array),<br/> [JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge),<br/> [JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set),<br/> [JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert),<br/> [JSON_REPLACE(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace),<br/> [JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove) |
Copy link
Member Author

@lilin90 lilin90 Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added missing links back.

| [日期运算](/functions-and-operators/date-and-time-functions.md) | [`DATE_FORMAT()`](https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format) |

### 禁止特定表达式下推
Expand Down Expand Up @@ -140,7 +140,7 @@ desc mysql.expr_pushdown_blacklist;

以下示例首先将运算符 `<` 及 `>` 加入黑名单,然后将运算符 `>` 从黑名单中移出。

黑名单是否生效可以从 `explain` 结果中进行观察(参见[如何理解 `explain` 结果](/query-execution-plan.md))。
黑名单是否生效可以从 `explain` 结果中进行观察(参见[`EXPLAIN` 简介](/query-execution-plan.md#explain-简介))。

1. 对于以下 SQL 语句,`where` 条件中的 `a < 2` 和 `a > 2` 可以下推到 TiKV 进行计算。

Expand Down Expand Up @@ -225,7 +225,7 @@ desc mysql.expr_pushdown_blacklist;
Query OK, 0 rows affected (0.00 sec)
```

5. 重新观察执行计划,`<` 和 `>` 表达式又可以重新被下推到 TiKV Coprocessor。
5. 重新观察执行计划,可以看到只有 `>` 表达式被重新下推到 TiKV Coprocessor,`<` 表达式仍然被禁用下推
Copy link
Member Author

@lilin90 lilin90 Jul 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzmhhh123 FYI. I've confirmed it with @winoros.


{{< copyable "sql" >}}

Expand Down
59 changes: 36 additions & 23 deletions troubleshoot-hot-spot-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Key: tablePrefix{tableID}_recordPrefixSep{rowID}
Value: [col1, col2, col3, col4]
```

其中 Key 的 tablePrefix/recordPrefixSep 都是特定的字符串常量,用于在 KV 空间内区分其他数据。
其中 Key 的 `tablePrefix` 和 `recordPrefixSep` 都是特定的字符串常量,用于在 KV 空间内区分其他数据。

对于 Index 数据,会按照如下规则编码成 Key-Value pair:

Expand All @@ -33,7 +33,7 @@ Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue
Value: rowID
```

Index 数据还需要考虑 Unique Index 和非 Unique Index 两种情况,对于 Unique Index,可以按照上述编码规则。但是对于非 Unique Index,通过这种编码并不能构造出唯一的 Key,因为同一个 Index 的 tablePrefix{tableID}_indexPrefixSep{indexID} 都一样,可能有多行数据的 ColumnsValue 是一样的,所以对于非 Unique Index 的编码做了一点调整:
Index 数据还需要考虑 Unique Index 和非 Unique Index 两种情况,对于 Unique Index,可以按照上述编码规则。但是对于非 Unique Index,通过这种编码并不能构造出唯一的 Key,因为同一个 Index 的 `tablePrefix{tableID}_indexPrefixSep{indexID}` 都一样,可能有多行数据的 `ColumnsValue` 是一样的,所以对于非 Unique Index 的编码做了一点调整:

```text
Key: tablePrefix{tableID}_indexPrefixSep{indexID}_indexedColumnsValue_rowID
Expand All @@ -42,7 +42,7 @@ Value: null

### 表热点

从 TiDB 编码规则可知,同一个表的数据会在以表 id 开头为前缀的一个 range 中,数据的顺序按照 RowID 的值顺序排列。在表 insert 的过程中如果 RowID 的值是递增的,则插入的行只能在末端追加。当 region 达到一定的大小之后会进行分裂,分裂之后还是只能在 range 范围的末端追加,永远只能在一个 region 上进行 insert 操作,形成热点。
从 TiDB 编码规则可知,同一个表的数据会在以表 ID 开头为前缀的一个 range 中,数据的顺序按照 RowID 的值顺序排列。在表 insert 的过程中如果 RowID 的值是递增的,则插入的行只能在末端追加。当 Region 达到一定的大小之后会进行分裂,分裂之后还是只能在 range 范围的末端追加,永远只能在一个 Region 上进行 insert 操作,形成热点。

常见的 increment 类型自增主键就是顺序递增的,默认情况下,在主键为整数型时,会用主键值当做 RowID ,此时 RowID 为顺序递增,在大量 insert 时形成表的写入热点。

Expand All @@ -58,15 +58,15 @@ Value: null

- 判断写热点依据:打开监控面板 TiKV-Trouble-Shooting 中 Hot Write 面板(如下图所示),观察 Raftstore CPU 监控是否存在个别 TiKV 节点的指标明显高于其他节点的现象。

- 判断读热点依据:打开监控面板 TIKV-Details 中 Thread_CPU,查看 coprocessor cpu 有没有明显的某个 tikv 特别高。
- 判断读热点依据:打开监控面板 TIKV-Details 中 Thread_CPU,查看 coprocessor cpu 有没有明显的某个 TiKV 特别高。

## 使用 TiDB Dashboard 定位热点表

[TiDB Dashboard](/dashboard/dashboard-intro.md) 中的**流量可视化**功能可帮助用户缩小热点排查范围到表级别。以下是一个「热点可视化」功能展示的热力图样例,该图横坐标是时间,纵坐标排列了各个表和索引,颜色越亮代表其流量越大。可在工具栏中切换显示读或写流量。
[TiDB Dashboard](/dashboard/dashboard-intro.md) 中的[流量可视化](/dashboard/dashboard-key-visualizer.md)功能可帮助用户缩小热点排查范围到表级别。以下是流量可视化功能展示的一个热力图样例,该图横坐标是时间,纵坐标是各个表和索引,颜色越亮代表其流量越大。可在工具栏中切换显示读或写流量。

![Dashboard 示例1](/media/troubleshoot-hot-spot-issues-1.png)

当图中写入流量图出现以下明亮斜线(斜向上或斜向下)时,由于写入只出现在末端,随着表 region 数量变多,呈现出阶梯状。此时说明该表构成了写入热点:
当图中写入流量图出现以下明亮斜线(斜向上或斜向下)时,由于写入只出现在末端,随着表 Region 数量变多,呈现出阶梯状。此时说明该表构成了写入热点:

![Dashboard 示例2](/media/troubleshoot-hot-spot-issues-2.png)

Expand Down Expand Up @@ -99,69 +99,82 @@ CREATE TABLE:CREATE TABLE t (c int) SHARD_ROW_ID_BITS = 4;
ALTER TABLE:ALTER TABLE t SHARD_ROW_ID_BITS = 4;
```

SHARD_ROW_ID_BITS 的值可以动态修改,每次修改之后,只对新写入的数据生效。
`SHARD_ROW_ID_BITS` 的值可以动态修改,每次修改之后,只对新写入的数据生效。

TiDB alter-primary-key 参数设置为 false 时,会使用表的整数型主键作为 RowID,因为 SHARD_ROW_ID_BITS 会改变 RowID 生成规则,所以此时无法使用 SHARD_ROW_ID_BITS 选项。在 alter-primary-key 参数设置为 true 时,TiDB 在建表时不再使用整数型主键作为 RowID,此时带有整数型主键的表也可以使用 SHARD_ROW_ID_BITS 特性。
TiDB `alter-primary-key` 参数设置为 false 时,会使用表的整数型主键作为 RowID,因为 `SHARD_ROW_ID_BITS` 会改变 RowID 生成规则,所以此时无法使用 `SHARD_ROW_ID_BITS` 选项。在 `alter-primary-key` 参数设置为 true 时,TiDB 在建表时不再使用整数型主键作为 RowID,此时带有整数型主键的表也可以使用 `SHARD_ROW_ID_BITS` 特性。

以下是两张无主键情况下使用 SHARD_ROW_ID_BITS 打散热点后的流量图,第一张展示了打散前的情况,第二张展示了打散后的情况。
以下是两张无主键情况下使用 `SHARD_ROW_ID_BITS` 打散热点后的流量图,第一张展示了打散前的情况,第二张展示了打散后的情况。

![Dashboard 示例5](/media/troubleshoot-hot-spot-issues-5.png)

![Dashboard 示例6](/media/troubleshoot-hot-spot-issues-6.png)

从流量图可见,设置 SHARD_ROW_ID_BITS 后,流量热点由之前的只在一个 Region 上变得很分散。
从流量图可见,设置 `SHARD_ROW_ID_BITS` 后,流量热点由之前的只在一个 Region 上变得很分散。

## 使用 AUTO_RANDOM 处理自增主键热点表

使用 AUTO_RANDOM 处理自增主键热点表,适用于代替自增主键,解决自增主键带来的写入热点。
使用 `AUTO_RANDOM` 处理自增主键热点表,适用于代替自增主键,解决自增主键带来的写入热点。

> **注意:**
>
> 该功能目前还是实验性功能,不推荐生产环境使用。可使用以下配置启用:
>
> ```
> [experimental]\
> allow-auto-random = true
> ```

使用该功能后,将由 TiDB 生成随机分布且空间耗尽前不重复的主键,达到离散写入、打散写入热点的目的。

>注意,TiDB 生成的主键不再是自增的主键,可使用 LAST_INSERT_ID() 获取上次分配的主键值。
注意 TiDB 生成的主键不再是自增的主键,可使用 `LAST_INSERT_ID()` 获取上次分配的主键值。

将建表语句中的 AUTO_INCREMENT 改为 AUTO_RANDOM 即可使用该功能,适用于主键只需要保证唯一,不包含业务意义的场景。\
示例如下:
将建表语句中的 `AUTO_INCREMENT` 改为 `AUTO_RANDOM` 即可使用该功能,适用于主键只需要保证唯一,不包含业务意义的场景。示例如下:

{{< copyable "sql" >}}

```sql
CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b varchar(255));
INSERT INTO t (b) VALUES ("foo");
SELECT * FROM t;
```

```sql
> CREATE TABLE t (a BIGINT PRIMARY KEY AUTO_RANDOM, b varchar(255));
> INSERT INTO t (b) VALUES ("foo");
> SELECT * FROM t;
+------------+---+
| a | b |
+------------+---+
| 1073741825 | b |
+------------+---+
```

> SELECT LAST_INSERT_ID();
{{< copyable "sql" >}}

```sql
SELECT LAST_INSERT_ID();
```

```sql
+------------------+
| LAST_INSERT_ID() |
+------------------+
| 1073741825 |
+------------------+
```

以下是将 AUTO_INCREMENT 表改为 AUTO_RANDOM 打散热点后的流量图,第一张是 AUTO_INCREMENT,第二张是 AUTO_RANDOM。
以下是将 `AUTO_INCREMENT` 表改为 `AUTO_RANDOM` 打散热点后的流量图,第一张是 `AUTO_INCREMENT`,第二张是 `AUTO_RANDOM`

![Dashboard 示例7](/media/troubleshoot-hot-spot-issues-7.png)

![Dashboard 示例8](/media/troubleshoot-hot-spot-issues-8.png)

由流量图可见,使用 AUTO_RANDOM 代替 AUTO_INCREMENT 能很好地打散热点。
由流量图可见,使用 `AUTO_RANDOM` 代替 `AUTO_INCREMENT` 能很好地打散热点。

更详细的说明可以阅读 [AUTO_RANDOM](/auto-random.md) 文档。
更详细的说明参见 [`AUTO_RANDOM`](/auto-random.md) 文档。

## 小表热点的优化

TiDB 从 4.0 起支持下推计算结果缓存(即 Coprocessor Cache 功能。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,对于小表读热点能起到比较好的效果。
TiDB 从 4.0 起引入了 Coprocessor Cache 功能,支持下推计算结果缓存。开启该功能后,将在 TiDB 实例侧缓存下推给 TiKV 计算的结果,对于小表读热点能起到比较好的效果。

更详细的说明可以阅读[下推计算结果缓存](/coprocessor-cache.md#配置)文档
更详细的说明参见[下推计算结果缓存](/coprocessor-cache.md#配置)文档

**其他相关资料**:

Expand Down