From ef79fae3e1d4b51d140bf5f52ae55fde60a18f8d Mon Sep 17 00:00:00 2001 From: lilin90 Date: Tue, 14 Jul 2020 20:31:11 +0800 Subject: [PATCH 1/2] Optimize description and add missing links --- blacklist-control-plan.md | 8 ++--- troubleshoot-hot-spot-issues.md | 59 ++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/blacklist-control-plan.md b/blacklist-control-plan.md index 04ecf8a227e5..9134de50eeec 100644 --- a/blacklist-control-plan.md +++ b/blacklist-control-plan.md @@ -17,7 +17,7 @@ category: performance |**优化规则**|**规则名称**|**简介**| | :--- | :--- | :--- | | 列裁剪 | column_prune | 对于上层算子不需要的列,不在下层算子输出该列,减少计算 | -| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggression 计算 | +| 子查询去关联 | decorrelate | 尝试对相关子查询进行改写,将其转换为普通 join 或 aggregation 计算 | | 聚合消除 | aggregation_eliminate | 尝试消除执行计划中的某些不必要的聚合算子 | | 投影消除 | projection_eliminate | 消除执行计划中不必要的投影算子 | | 最大最小消除 | max_min_eliminate | 改写聚合中的 max/min 计算,转化为 `order by` + `limit 1` | @@ -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; ``` @@ -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],
[JSON_EXTRACT(json_doc, path[, path] ...)][json_extract],
[JSON_UNQUOTE(json_val)][json_unquote],
[JSON_OBJECT(key, val[, key, val] ...)][json_object],
[JSON_ARRAY([val[, val] ...])][json_array],
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)][json_merge],
[JSON_SET(json_doc, path, val[, path, val] ...)][json_set],
[JSON_INSERT(json_doc, path, val[, path, val] ...)][json_insert],
[JSON_REPLACE(json_doc, path, val[, path, val] ...)][json_replace],
[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),
[JSON_EXTRACT(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html#function_json-extract),
[JSON_UNQUOTE(json_val)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-unquote),
[JSON_OBJECT(key, val[, key, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-object),
[JSON_ARRAY([val[, val] ...])](https://dev.mysql.com/doc/refman/5.7/en/json-creation-functions.html#function_json-array),
[JSON_MERGE(json_doc, json_doc[, json_doc] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-merge),
[JSON_SET(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-set),
[JSON_INSERT(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-insert),
[JSON_REPLACE(json_doc, path, val[, path, val] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-replace),
[JSON_REMOVE(json_doc, path[, path] ...)](https://dev.mysql.com/doc/refman/5.7/en/json-modification-functions.html#function_json-remove) | | [日期运算](/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) | ### 禁止特定表达式下推 @@ -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 进行计算。 diff --git a/troubleshoot-hot-spot-issues.md b/troubleshoot-hot-spot-issues.md index 6d8480ce4499..0761ab7d6ff1 100644 --- a/troubleshoot-hot-spot-issues.md +++ b/troubleshoot-hot-spot-issues.md @@ -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: @@ -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 @@ -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 时形成表的写入热点。 @@ -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) @@ -99,47 +99,60 @@ 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() | +------------------+ @@ -147,21 +160,21 @@ TiDB alter-primary-key 参数设置为 false 时,会使用表的整数型主 +------------------+ ``` -以下是将 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#配置)文档。 **其他相关资料**: From b45da1b19c396382f7d139f378bf87cfe2f0d21c Mon Sep 17 00:00:00 2001 From: lilin90 Date: Tue, 14 Jul 2020 21:30:05 +0800 Subject: [PATCH 2/2] Fix one description --- blacklist-control-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blacklist-control-plan.md b/blacklist-control-plan.md index 9134de50eeec..46859642490c 100644 --- a/blacklist-control-plan.md +++ b/blacklist-control-plan.md @@ -225,7 +225,7 @@ desc mysql.expr_pushdown_blacklist; Query OK, 0 rows affected (0.00 sec) ``` -5. 重新观察执行计划,`<` 和 `>` 表达式又可以重新被下推到 TiKV Coprocessor。 +5. 重新观察执行计划,可以看到只有 `>` 表达式被重新下推到 TiKV Coprocessor,`<` 表达式仍然被禁用下推。 {{< copyable "sql" >}}