LEFT\|RIGHT [OUTER] JOIN
| Y | Y | Y | Y | Y | Y | Y | Y |
-| `UNION`,`UNION ALL` | Y | Y | Y | Y | Y | Y | Y | Y |
-| [`EXCEPT` 和 `INTERSECT` 运算符](/functions-and-operators/set-operators.md) | Y | Y | Y | Y | Y | Y | Y | N |
-| `GROUP BY`,`ORDER BY` | Y | Y | Y | Y | Y | Y | Y | Y |
-| [窗口函数](/functions-and-operators/window-functions.md) | Y | Y | Y | Y | Y | Y | Y | Y |
-| [公共表表达式 (CTE)](/sql-statements/sql-statement-with.md) | Y | Y | Y | Y | Y | Y | N | N |
-| `START TRANSACTION`,`COMMIT`,`ROLLBACK` | Y | Y | Y | Y | Y | Y | Y | Y |
-| [`EXPLAIN`](/sql-statements/sql-statement-explain.md) | Y | Y | Y | Y | Y | Y | Y | Y |
-| [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) | Y | Y | Y | Y | Y | Y | Y | Y |
-| [用户自定义变量](/user-defined-variables.md) | E | E | E | E | E | E | E | E |
-| [`BATCH [ON COLUMN] LIMIT INTEGER DELETE`](/sql-statements/sql-statement-batch.md) | Y | Y | N | N | N | N | N | N |
-| [`BATCH [ON COLUMN] LIMIT INTEGER INSERT/UPDATE/REPLACE`](/sql-statements/sql-statement-batch.md) | Y | N | N | N | N | N | N | N |
-| [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) | Y | E | N | N | N | N | N | N |
-| [表级锁 (Table Lock)](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) | E | E | E | E | E | E | E | E |
-| [物化列式存储的查询结果](/tiflash/tiflash-results-materialization.md) | E | N | N | N | N | N | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| SQL 语句 [^3] | 6.5 | 6.1 | 5.4 | 5.3 | 5.2 | 5.1 | 5.0 | 4.0 |
++===================================================================================================+:===:+:===:+:===:+:===:+:===:+:===:+:===:+:===:+
+| `SELECT`,`INSERT`,`UPDATE`,`DELETE`,`REPLACE` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `INSERT ON DUPLICATE KEY UPDATE` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `LOAD DATA INFILE` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `SELECT INTO OUTFILE` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `INNER JOIN`, `LEFT|RIGHT [OUTER] JOIN` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `UNION`,`UNION ALL` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`EXCEPT` 和 `INTERSECT` 运算符](/functions-and-operators/set-operators.md) | Y | Y | Y | Y | Y | Y | Y | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `GROUP BY`,`ORDER BY` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [窗口函数](/functions-and-operators/window-functions.md) | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [公共表表达式 (CTE)](/sql-statements/sql-statement-with.md) | Y | Y | Y | Y | Y | Y | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| `START TRANSACTION`,`COMMIT`,`ROLLBACK` | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`EXPLAIN`](/sql-statements/sql-statement-explain.md) | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`EXPLAIN ANALYZE`](/sql-statements/sql-statement-explain-analyze.md) | Y | Y | Y | Y | Y | Y | Y | Y |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [用户自定义变量](/user-defined-variables.md) | E | E | E | E | E | E | E | E |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`BATCH [ON COLUMN] LIMIT INTEGER DELETE`](/sql-statements/sql-statement-batch.md) | Y | Y | N | N | N | N | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`BATCH [ON COLUMN] LIMIT INTEGER INSERT/UPDATE/REPLACE`](/sql-statements/sql-statement-batch.md) | Y | N | N | N | N | N | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [`ALTER TABLE ... COMPACT`](/sql-statements/sql-statement-alter-table-compact.md) | Y | E | N | N | N | N | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [表级锁 (Table Lock)](/sql-statements/sql-statement-lock-tables-and-unlock-tables.md) | E | E | E | E | E | E | E | E |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
+| [物化列式存储的查询结果](/tiflash/tiflash-results-materialization.md) | E | N | N | N | N | N | N | N |
++---------------------------------------------------------------------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
## 高级 SQL 功能
diff --git a/best-practices/tidb-best-practices.md b/best-practices/tidb-best-practices.md
index 887c0068ce19..6e7109c5a418 100644
--- a/best-practices/tidb-best-practices.md
+++ b/best-practices/tidb-best-practices.md
@@ -1,197 +1,197 @@
----
-title: TiDB 最佳实践
----
-
-# TiDB 最佳实践
-
-本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/OLTP 优化技巧,特别是一些 TiDB 专有的优化开关。
-
-建议先阅读讲解 TiDB 原理的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),再来看这篇文章。
-
-## 前言
-
-数据库是一个通用的基础组件,在开发过程中会考虑到多种目标场景,在具体的业务场景中,需要根据业务的实际情况对数据的参数或者使用方式进行调整。
-
-TiDB 是一个兼容 MySQL 协议和语法的分布式数据库,但是由于其内部实现,特别是支持分布式存储以及分布式事务,使得一些使用方法和 MySQL 有所区别。
-
-## 基本概念
-
-TiDB 的最佳实践与其实现原理密切相关,建议读者先了解一些基本的实现机制,包括 Raft、分布式事务、数据分片、负载均衡、SQL 到 KV 的映射方案、二级索引的实现方法、分布式执行引擎。下面会做一点简单的介绍,更详细的信息可以参考 PingCAP 公众号以及知乎专栏的一些文章。
-
-### Raft
-
-Raft 是一种一致性协议,能提供强一致的数据复制保证,TiDB 最底层用 Raft 来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。
-
-相比 Master-Slave 方式的同步,同样是保存三副本,Raft 的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。
-
-### 分布式事务
-
-TiDB 提供完整的分布式事务,事务模型是在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上做了一些优化。具体的实现可以参考[《Percolator 和 TiDB 事务算法》](https://pingcap.com/blog-cn/percolator-and-txn/)这篇文章。本文档只讨论以下几点:
-
-+ 乐观锁
-
- TiDB 的乐观事务模型,只有在真正提交的时候,才会做冲突检测。如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。在冲突严重的场景下,推荐使用悲观锁,或在系统架构层面解决问题,比如将计数器放在 Redis 中。
-
-+ 悲观锁
-
- TiDB 的悲观事务模式,悲观事务的行为和 MySQL 基本一致,在执行阶段就会上锁,先到先得,避免冲突情况下的重试,可以保证有较多冲突的事务的成功率。悲观锁同时解决了希望通过 `select for update` 对数据提前锁定的场景。但如果业务场景本身冲突较少,乐观锁的性能会更有优势。
-
-+ 事务大小限制
-
- 由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制:
-
- - 单个事务包含的 SQL 语句不超过 5000 条(默认)
- - 单条 KV entry 不超过 6MB(默认)
- - KV entry 的总大小不超过 10G
-
- 在 Google 的 Cloud Spanner 上面,也有[类似的限制](https://cloud.google.com/spanner/docs/limits)。
-
-### 数据分片
-
-TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key 的范围,从 `StartKey` 到 `EndKey` 的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。这部分用户不需要担心。
-
-### 负载均衡
-
-PD 会根据整个 TiKV 集群的状态,对集群的负载进行调度。调度是以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。
-
-### SQL on KV
-
-TiDB 自动将 SQL 结构映射为 KV 结构。具体的可以参考[《三篇文章了解 TiDB 技术内幕 - 说计算》](https://pingcap.com/blog-cn/tidb-internal-2/)这篇文档。简单来说,TiDB 执行了以下操作:
-
-+ 一行数据映射为一个 KV,Key 以 `TableID` 构造前缀,以行 ID 为后缀
-+ 一条索引映射为一个 KV,Key 以 `TableID+IndexID` 构造前缀,以索引值构造后缀
-
-可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key 空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会在很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。同样,如果所有的数据读取操作也都集中在很小的一个范围内(比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。
-
-### 二级索引
-
-TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。
-
-+ 二级索引是否越多越好
-
- 二级索引能加速查询,但是要注意新增一个索引是有副作用的。上一节介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。
-
-+ 对哪些列建索引比较合适
-
- 上文提到,索引很重要但不是越多越好,因此需要根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引:
-
- - 区分度比较大的列,通过索引能显著地减少过滤后的行数
- - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面
-
- 这里举一个例子,假设常用的查询是 `select * from t where c1 = 10 and c2 = 100 and c3 > 10`,那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。
-
-+ 通过索引查询和直接扫描 Table 的区别
-
- TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。
-
- 如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。
-
- 以下情况不会涉及到两次访问的问题:
-
- - 索引中的列已经满足了查询需求。比如 Table `t` 上面的列 `c` 有索引,查询是 `select c from t where c > 10;`,这个时候,只需要访问索引,就可以拿到所需要的全部数据。这种情况称之为覆盖索引 (Covering Index)。所以如果很关注查询性能,可以将部分不需要过滤但是需要在查询结果中返回的列放入索引中,构造成组合索引,比如这个例子:`select c1, c2 from t where c1 > 10;`,要优化这个查询可以创建组合索引 `Index c12 (c1, c2)`。
- - 表的 Primary Key 是整数类型。在这种情况下,TiDB 会将 Primary Key 的值当做行 ID,所以如果查询条件是在 PK 上面,那么可以直接构造出行 ID 的范围,直接扫描 Table 数据,获取结果。
-
-+ 查询并发度
-
- 数据分散在很多 Region 上,所以 TiDB 在做查询的时候会并发进行,默认的并发度比较保守,因为过高的并发度会消耗大量的系统资源,且对于 OLTP 类型的查询,往往不会涉及到大量的数据,较低的并发度已经可以满足需求。对于 OLAP 类型的 Query,往往需要较高的并发度。所以 TiDB 支持通过 System Variable 来调整查询并发度。
-
- - [tidb_distsql_scan_concurrency](/system-variables.md#tidb_distsql_scan_concurrency)
-
- 在进行扫描数据的时候的并发度,这里包括扫描 Table 以及索引数据。
-
- - [tidb_index_lookup_size](/system-variables.md#tidb_index_lookup_size)
-
- 如果是需要访问索引获取行 ID 之后再访问 Table 数据,那么每次会把一批行 ID 作为一次请求去访问 Table 数据,这个参数可以设置 Batch 的大小,较大的 Batch 会使得延迟增加,较小的 Batch 可能会造成更多的查询次数。这个参数的合适大小与查询涉及的数据量有关。一般不需要调整。
-
- - [tidb_index_lookup_concurrency](/system-variables.md#tidb_index_lookup_concurrency)
-
- 如果是需要访问索引获取行 ID 之后再访问 Table 数据,每次通过行 ID 获取数据时候的并发度通过这个参数调节。
-
-+ 通过索引保证结果顺序
-
- 索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 [tidb_index_serial_scan_concurrency](/system-variables.md#tidb_index_serial_scan_concurrency) 变量进行并发度调整。
-
-+ 逆序索引
-
- 目前 TiDB 支持对索引进行逆序 Scan,目前速度比顺序 Scan 慢一些,通常情况下慢 20%,在数据频繁修改造成版本较多的情况下,会慢的更多。如果可能,建议避免对索引的逆序 Scan。
-
-## 场景与实践
-
-上一节我们讨论了一些 TiDB 基本的实现机制及其对使用带来的影响,本节我们从具体的使用场景出发,谈一些更为具体的操作实践。我们以从部署到支撑业务这条链路为序,进行讨论。
-
-### 部署
-
-在部署之前请务必阅读 [TiDB 部署建议以及对硬件的需求](/hardware-and-software-requirements.md)。
-
-推荐通过 [TiUP](/production-deployment-using-tiup.md) 部署 TiDB 集群,这个工具可以部署、停止、销毁、升级整个集群,非常方便易用。非常不推荐手动部署,后期的维护和升级会很麻烦。
-
-### 导入数据
-
-为了提高导入数据期间的写入性能,可以对 TiKV 的参数进行调优,具体的文档查看 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。
-
-### 写入
-
-上面提到了 TiDB 对单个事务的大小有限制,这层限制是在 KV 层面,反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。
-
-> **注意:**
->
-> 对事务的大小限制,要考虑 TiDB 做编码以及事务额外 Key 的开销,在使用的时候,**建议每个事务的行数不超过 200 行,且单行数据小于 100k**,否则可能性能不佳。
-
-建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。
-
-在删除大量数据的时候,建议使用 `Delete from t where xx limit 5000;` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件。
-
-如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 清理掉),影响后面的 `Delete` 语句。如果有可能,建议把 `Where` 条件细化。举个例子,假设要删除 2017-05-26 当天的所有数据,那么可以这样做:
-
-```SQL
-for i from 0 to 23:
- while affected_rows > 0:
- delete from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000;
- affected_rows = select affected_rows()
-```
-
-上面是一段伪代码,意思就是要把大块的数据拆成小块删除,以避免删除过程中前面的 Delete 语句影响后面的 Delete 语句。
-
-### 查询
-
-看业务的查询需求以及具体的语句,可以参考 [TiDB 专用系统变量和语法](/system-variables.md)这篇文档。可以通过 SET 语句控制 SQL 执行的并发度,另外通过 Hint 控制 Join 物理算子选择。
-
-另外 MySQL 标准的索引选择 Hint 语法,也可以用,通过 `Use Index/Ignore Index hint` 控制优化器选择索引。
-
-如果是个 OLTP 和 OLAP 混合类型的业务,可以把 TP 请求和 AP 请求发送到不同的 tidb-server 上,这样能够减小 AP 业务对于 TP 业务的影响。 承载 AP 业务的 tidb-server 推荐使用高配的机器,比如 CPU 核数比较多,内存比较大。
-
-但彻底的隔离 OLTP 和 OLAP,推荐将 OLAP 的业务跑在 TiFlash 上。TiFlash 是列存引擎,在 OLAP 的分析查询场景上,性能极具亮点,TiFlash 可以在存储层上做到物理隔离,并可做到一致性读取。
-
-### 监控和日志
-
-Metrics 系统是了解系统状态的最佳方法,建议所有的用户都部署监控系统。
-
-TiDB [使用 Grafana + Prometheus 监控系统状态](/tidb-monitoring-framework.md)。如果使用 TiUP 部署集群,那么会自动部署和配置监控系统。
-
-监控系统中的监控项很多,大部分是给 TiDB 开发者查看的内容,如果没有对源代码比较深入的了解,并没有必要了解这些监控项。我们会精简出一些和业务相关或者是系统关键组件状态相关的监控项,放在一个独立的 `overview` 面板中,供用户使用。
-
-除了监控之外,查看日志也是了解系统状态的常用方法。TiDB 的三个组件 tidb-server/tikv-server/pd-server 都有一个 `--log-file` 的参数。如果启动的时候设置了这个参数,那么日志会保存着参数所设置的文件的位置,另外会自动的按天对 Log 文件做归档。如果没有设置 `--log-file` 参数,日志会输出在 `stderr` 中。
-
-从 4.0 版本开始,从解决易用性的角度出发,提供了 [TiDB Dashboard](/dashboard/dashboard-intro.md) UI 系统,通过浏览器访问 `http://PD_IP:PD_PORT/dashboard` 即可打开 TiDB Dashboard。TiDB Dashboard 可以提供集群状态、性能分析、流量可视化、SQL 诊断、日志搜索等功能。
-
-### 文档
-
-了解一个系统或者解决使用中的问题最好的方法是阅读文档,明白实现原理。TiDB 有大量的官方文档,希望大家在遇到问题的时候能先尝试通过文档或者搜索 Issue list 寻找解决方案。官方文档查看 [docs-cn](https://github.com/pingcap/docs-cn)。如果希望阅读英文文档,可以查看 [docs](https://github.com/pingcap/docs)。
-
-其中的 [FAQ](/faq/tidb-faq.md) 和[故障诊断](/troubleshoot-tidb-cluster.md)章节建议大家仔细阅读。另外 TiDB 还有一些不错的工具,也有配套的文档,具体的见各项工具的 GitHub 页面。
-
-除了文档之外,还有很多不错的文章介绍 TiDB 的各项技术细节内幕,大家可以关注下面这些文章发布渠道:
-
-+ 公众号:微信搜索 PingCAP
-+ 知乎专栏:[TiDB 的后花园](https://zhuanlan.zhihu.com/newsql)
-+ [官方博客](https://pingcap.com/blog-cn/)
-
-## TiDB 的最佳适用场景
-
-简单来说,TiDB 适合具备下面这些特点的场景:
-
-+ 数据量大,单机保存不下
-+ 不希望做 Sharding 或者懒得做 Sharding
-+ 访问模式上没有明显的热点
-+ 需要事务、需要强一致、需要灾备
-+ 希望 Real-Time HTAP,减少存储链路
+---
+title: TiDB 最佳实践
+---
+
+# TiDB 最佳实践
+
+本文档总结使用 TiDB 时的一些最佳实践,主要涉及 SQL 使用和 OLAP/OLTP 优化技巧,特别是一些 TiDB 专有的优化开关。
+
+建议先阅读讲解 TiDB 原理的三篇文章([讲存储](https://pingcap.com/blog-cn/tidb-internal-1/),[说计算](https://pingcap.com/blog-cn/tidb-internal-2/),[谈调度](https://pingcap.com/blog-cn/tidb-internal-3/)),再来看这篇文章。
+
+## 前言
+
+数据库是一个通用的基础组件,在开发过程中会考虑到多种目标场景,在具体的业务场景中,需要根据业务的实际情况对数据的参数或者使用方式进行调整。
+
+TiDB 是一个兼容 MySQL 协议和语法的分布式数据库,但是由于其内部实现,特别是支持分布式存储以及分布式事务,使得一些使用方法和 MySQL 有所区别。
+
+## 基本概念
+
+TiDB 的最佳实践与其实现原理密切相关,建议读者先了解一些基本的实现机制,包括 Raft、分布式事务、数据分片、负载均衡、SQL 到 KV 的映射方案、二级索引的实现方法、分布式执行引擎。下面会做一点简单的介绍,更详细的信息可以参考 PingCAP 公众号以及知乎专栏的一些文章。
+
+### Raft
+
+Raft 是一种一致性协议,能提供强一致的数据复制保证,TiDB 最底层用 Raft 来同步数据。每次写入都要写入多数副本,才能对外返回成功,这样即使丢掉少数副本,也能保证系统中还有最新的数据。比如最大 3 副本的话,每次写入 2 副本才算成功,任何时候,只丢失一个副本的情况下,存活的两个副本中至少有一个具有最新的数据。
+
+相比 Master-Slave 方式的同步,同样是保存三副本,Raft 的方式更为高效,写入的延迟取决于最快的两个副本,而不是最慢的那个副本。所以使用 Raft 同步的情况下,异地多活成为可能。在典型的两地三中心场景下,每次写入只需要本数据中心以及离得近的一个数据中心写入成功就能保证数据的一致性,而并不需要三个数据中心都写成功。但是这并不意味着在任何场景都能构建跨机房部署的业务,当写入量比较大时候,机房之间的带宽和延迟成为关键因素,如果写入速度超过机房之间的带宽,或者是机房之间延迟过大,整个 Raft 同步机制依然无法很好的运转。
+
+### 分布式事务
+
+TiDB 提供完整的分布式事务,事务模型是在 [Google Percolator](https://research.google.com/pubs/pub36726.html) 的基础上做了一些优化。具体的实现可以参考[《Percolator 和 TiDB 事务算法》](https://pingcap.com/blog-cn/percolator-and-txn/)这篇文章。本文档只讨论以下几点:
+
++ 乐观锁
+
+ TiDB 的乐观事务模型,只有在真正提交的时候,才会做冲突检测。如果有冲突,则需要重试。这种模型在冲突严重的场景下,会比较低效,因为重试之前的操作都是无效的,需要重复做。举一个比较极端的例子,就是把数据库当做计数器用,如果访问的并发度比较高,那么一定会有严重的冲突,导致大量的重试甚至是超时。但是如果访问冲突并不十分严重,那么乐观锁模型具备较高的效率。在冲突严重的场景下,推荐使用悲观锁,或在系统架构层面解决问题,比如将计数器放在 Redis 中。
+
++ 悲观锁
+
+ TiDB 的悲观事务模式,悲观事务的行为和 MySQL 基本一致,在执行阶段就会上锁,先到先得,避免冲突情况下的重试,可以保证有较多冲突的事务的成功率。悲观锁同时解决了希望通过 `select for update` 对数据提前锁定的场景。但如果业务场景本身冲突较少,乐观锁的性能会更有优势。
+
++ 事务大小限制
+
+ 由于分布式事务要做两阶段提交,并且底层还需要做 Raft 复制,如果一个事务非常大,会使得提交过程非常慢,并且会卡住下面的 Raft 复制流程。为了避免系统出现被卡住的情况,我们对事务的大小做了限制:
+
+ - 单个事务包含的 SQL 语句不超过 5000 条(默认)
+ - 单条 KV entry 不超过 6MB(默认)
+ - KV entry 的总大小不超过 10G
+
+ 在 Google 的 Cloud Spanner 上面,也有[类似的限制](https://cloud.google.com/spanner/docs/limits)。
+
+### 数据分片
+
+TiKV 自动将底层数据按照 Key 的 Range 进行分片。每个 Region 是一个 Key 的范围,从 `StartKey` 到 `EndKey` 的左闭右开区间。Region 中的 Key-Value 总量超过一定值,就会自动分裂。这部分用户不需要担心。
+
+### 负载均衡
+
+PD 会根据整个 TiKV 集群的状态,对集群的负载进行调度。调度是以 Region 为单位,以 PD 配置的策略为调度逻辑,自动完成。
+
+### SQL on KV
+
+TiDB 自动将 SQL 结构映射为 KV 结构。具体的可以参考[《三篇文章了解 TiDB 技术内幕 - 说计算》](https://pingcap.com/blog-cn/tidb-internal-2/)这篇文档。简单来说,TiDB 执行了以下操作:
+
++ 一行数据映射为一个 KV,Key 以 `TableID` 构造前缀,以行 ID 为后缀
++ 一条索引映射为一个 KV,Key 以 `TableID+IndexID` 构造前缀,以索引值构造后缀
+
+可以看到,对于一个表中的数据或者索引,会具有相同的前缀,这样在 TiKV 的 Key 空间内,这些 Key-Value 会在相邻的位置。那么当写入量很大,并且集中在一个表上面时,就会造成写入的热点,特别是连续写入的数据中某些索引值也是连续的(比如 update time 这种按时间递增的字段),会在很少的几个 Region 上形成写入热点,成为整个系统的瓶颈。同样,如果所有的数据读取操作也都集中在很小的一个范围内(比如在连续的几万或者十几万行数据上),那么可能造成数据的访问热点。
+
+### 二级索引
+
+TiDB 支持完整的二级索引,并且是全局索引,很多查询可以通过索引来优化。如果利用好二级索引,对业务非常重要,很多 MySQL 上的经验在 TiDB 这里依然适用,不过 TiDB 还有一些自己的特点,需要注意,这一节主要讨论在 TiDB 上使用二级索引的一些注意事项。
+
++ 二级索引是否越多越好
+
+ 二级索引能加速查询,但是要注意新增一个索引是有副作用的。上一节介绍了索引的存储模型,那么每增加一个索引,在插入一条数据的时候,就要新增一个 Key-Value,所以索引越多,写入越慢,并且空间占用越大。另外过多的索引也会影响优化器运行时间,并且不合适的索引会误导优化器。所以索引并不是越多越好。
+
++ 对哪些列建索引比较合适
+
+ 上文提到,索引很重要但不是越多越好,因此需要根据具体的业务特点创建合适的索引。原则上需要对查询中需要用到的列创建索引,目的是提高性能。下面几种情况适合创建索引:
+
+ - 区分度比较大的列,通过索引能显著地减少过滤后的行数
+ - 有多个查询条件时,可以选择组合索引,注意需要把等值条件的列放在组合索引的前面
+
+ 这里举一个例子,假设常用的查询是 `select * from t where c1 = 10 and c2 = 100 and c3 > 10`,那么可以考虑建立组合索引 `Index cidx (c1, c2, c3)`,这样可以用查询条件构造出一个索引前缀进行 Scan。
+
++ 通过索引查询和直接扫描 Table 的区别
+
+ TiDB 实现了全局索引,所以索引和 Table 中的数据并不一定在一个数据分片上。通过索引查询的时候,需要先扫描索引,得到对应的行 ID,然后通过行 ID 去取数据,所以可能会涉及到两次网络请求,会有一定的性能开销。
+
+ 如果查询涉及到大量的行,那么扫描索引是并发进行,只要第一批结果已经返回,就可以开始去取 Table 的数据,所以这里是一个并行 + Pipeline 的模式,虽然有两次访问的开销,但是延迟并不会很大。
+
+ 以下情况不会涉及到两次访问的问题:
+
+ - 索引中的列已经满足了查询需求。比如 Table `t` 上面的列 `c` 有索引,查询是 `select c from t where c > 10;`,这个时候,只需要访问索引,就可以拿到所需要的全部数据。这种情况称之为覆盖索引 (Covering Index)。所以如果很关注查询性能,可以将部分不需要过滤但是需要在查询结果中返回的列放入索引中,构造成组合索引,比如这个例子:`select c1, c2 from t where c1 > 10;`,要优化这个查询可以创建组合索引 `Index c12 (c1, c2)`。
+ - 表的 Primary Key 是整数类型。在这种情况下,TiDB 会将 Primary Key 的值当做行 ID,所以如果查询条件是在 PK 上面,那么可以直接构造出行 ID 的范围,直接扫描 Table 数据,获取结果。
+
++ 查询并发度
+
+ 数据分散在很多 Region 上,所以 TiDB 在做查询的时候会并发进行,默认的并发度比较保守,因为过高的并发度会消耗大量的系统资源,且对于 OLTP 类型的查询,往往不会涉及到大量的数据,较低的并发度已经可以满足需求。对于 OLAP 类型的 Query,往往需要较高的并发度。所以 TiDB 支持通过 System Variable 来调整查询并发度。
+
+ - [tidb_distsql_scan_concurrency](/system-variables.md#tidb_distsql_scan_concurrency)
+
+ 在进行扫描数据的时候的并发度,这里包括扫描 Table 以及索引数据。
+
+ - [tidb_index_lookup_size](/system-variables.md#tidb_index_lookup_size)
+
+ 如果是需要访问索引获取行 ID 之后再访问 Table 数据,那么每次会把一批行 ID 作为一次请求去访问 Table 数据,这个参数可以设置 Batch 的大小,较大的 Batch 会使得延迟增加,较小的 Batch 可能会造成更多的查询次数。这个参数的合适大小与查询涉及的数据量有关。一般不需要调整。
+
+ - [tidb_index_lookup_concurrency](/system-variables.md#tidb_index_lookup_concurrency)
+
+ 如果是需要访问索引获取行 ID 之后再访问 Table 数据,每次通过行 ID 获取数据时候的并发度通过这个参数调节。
+
++ 通过索引保证结果顺序
+
+ 索引除了可以用来过滤数据之外,还能用来对数据排序,首先按照索引的顺序获取行 ID,然后再按照行 ID 的返回顺序返回行的内容,这样可以保证返回结果按照索引列有序。前面提到了扫索引和获取 Row 之间是并行 + Pipeline 模式,如果要求按照索引的顺序返回 Row,那么这两次查询之间的并发度设置的太高并不会降低延迟,所以默认的并发度比较保守。可以通过 [tidb_index_serial_scan_concurrency](/system-variables.md#tidb_index_serial_scan_concurrency) 变量进行并发度调整。
+
++ 逆序索引
+
+ 目前 TiDB 支持对索引进行逆序 Scan,目前速度比顺序 Scan 慢一些,通常情况下慢 20%,在数据频繁修改造成版本较多的情况下,会慢的更多。如果可能,建议避免对索引的逆序 Scan。
+
+## 场景与实践
+
+上一节我们讨论了一些 TiDB 基本的实现机制及其对使用带来的影响,本节我们从具体的使用场景出发,谈一些更为具体的操作实践。我们以从部署到支撑业务这条链路为序,进行讨论。
+
+### 部署
+
+在部署之前请务必阅读 [TiDB 部署建议以及对硬件的需求](/hardware-and-software-requirements.md)。
+
+推荐通过 [TiUP](/production-deployment-using-tiup.md) 部署 TiDB 集群,这个工具可以部署、停止、销毁、升级整个集群,非常方便易用。非常不推荐手动部署,后期的维护和升级会很麻烦。
+
+### 导入数据
+
+为了提高导入数据期间的写入性能,可以对 TiKV 的参数进行调优,具体的文档查看 [TiKV 性能参数调优](/tune-tikv-memory-performance.md)。
+
+### 写入
+
+上面提到了 TiDB 对单个事务的大小有限制,这层限制是在 KV 层面,反映在 SQL 层面的话,简单来说一行数据会映射为一个 KV entry,每多一个索引,也会增加一个 KV entry。
+
+> **注意:**
+>
+> 对事务的大小限制,要考虑 TiDB 做编码以及事务额外 Key 的开销,在使用的时候,**建议每个事务的行数不超过 200 行,且单行数据小于 100k**,否则可能性能不佳。
+
+建议无论是 Insert,Update 还是 Delete 语句,都通过分 Batch 或者是加 Limit 的方式限制。
+
+在删除大量数据的时候,建议使用 `Delete from t where xx limit 5000;` 这样的方案,通过循环来删除,用 `Affected Rows == 0` 作为循环结束条件。
+
+如果一次删除的数据量非常大,这种循环的方式会越来越慢,因为每次删除都是从前向后遍历,前面的删除之后,短时间内会残留不少删除标记(后续会被 GC 清理掉),影响后面的 `Delete` 语句。如果有可能,建议把 `Where` 条件细化。举个例子,假设要删除 2017-05-26 当天的所有数据,那么可以这样做:
+
+```SQL
+for i from 0 to 23:
+ while affected_rows > 0:
+ delete from t where insert_time >= i:00:00 and insert_time < (i+1):00:00 limit 5000;
+ affected_rows = select affected_rows()
+```
+
+上面是一段伪代码,意思就是要把大块的数据拆成小块删除,以避免删除过程中前面的 Delete 语句影响后面的 Delete 语句。
+
+### 查询
+
+看业务的查询需求以及具体的语句,可以参考 [TiDB 专用系统变量和语法](/system-variables.md)这篇文档。可以通过 SET 语句控制 SQL 执行的并发度,另外通过 Hint 控制 Join 物理算子选择。
+
+另外 MySQL 标准的索引选择 Hint 语法,也可以用,通过 `Use Index/Ignore Index hint` 控制优化器选择索引。
+
+如果是个 OLTP 和 OLAP 混合类型的业务,可以把 TP 请求和 AP 请求发送到不同的 tidb-server 上,这样能够减小 AP 业务对于 TP 业务的影响。 承载 AP 业务的 tidb-server 推荐使用高配的机器,比如 CPU 核数比较多,内存比较大。
+
+但彻底的隔离 OLTP 和 OLAP,推荐将 OLAP 的业务跑在 TiFlash 上。TiFlash 是列存引擎,在 OLAP 的分析查询场景上,性能极具亮点,TiFlash 可以在存储层上做到物理隔离,并可做到一致性读取。
+
+### 监控和日志
+
+Metrics 系统是了解系统状态的最佳方法,建议所有的用户都部署监控系统。
+
+TiDB [使用 Grafana + Prometheus 监控系统状态](/tidb-monitoring-framework.md)。如果使用 TiUP 部署集群,那么会自动部署和配置监控系统。
+
+监控系统中的监控项很多,大部分是给 TiDB 开发者查看的内容,如果没有对源代码比较深入的了解,并没有必要了解这些监控项。我们会精简出一些和业务相关或者是系统关键组件状态相关的监控项,放在一个独立的 `overview` 面板中,供用户使用。
+
+除了监控之外,查看日志也是了解系统状态的常用方法。TiDB 的三个组件 tidb-server/tikv-server/pd-server 都有一个 `--log-file` 的参数。如果启动的时候设置了这个参数,那么日志会保存着参数所设置的文件的位置,另外会自动的按天对 Log 文件做归档。如果没有设置 `--log-file` 参数,日志会输出在 `stderr` 中。
+
+从 4.0 版本开始,从解决易用性的角度出发,提供了 [TiDB Dashboard](/dashboard/dashboard-intro.md) UI 系统,通过浏览器访问 `http://PD_IP:PD_PORT/dashboard` 即可打开 TiDB Dashboard。TiDB Dashboard 可以提供集群状态、性能分析、流量可视化、SQL 诊断、日志搜索等功能。
+
+### 文档
+
+了解一个系统或者解决使用中的问题最好的方法是阅读文档,明白实现原理。TiDB 有大量的官方文档,希望大家在遇到问题的时候能先尝试通过文档或者搜索 Issue list 寻找解决方案。官方文档查看 [docs-cn](https://github.com/pingcap/docs-cn)。如果希望阅读英文文档,可以查看 [docs](https://github.com/pingcap/docs)。
+
+其中的 [FAQ](/faq/tidb-faq.md) 和[故障诊断](/troubleshoot-tidb-cluster.md)章节建议大家仔细阅读。另外 TiDB 还有一些不错的工具,也有配套的文档,具体的见各项工具的 GitHub 页面。
+
+除了文档之外,还有很多不错的文章介绍 TiDB 的各项技术细节内幕,大家可以关注下面这些文章发布渠道:
+
++ 公众号:微信搜索 PingCAP
++ 知乎专栏:[TiDB 的后花园](https://zhuanlan.zhihu.com/newsql)
++ [官方博客](https://pingcap.com/blog-cn/)
+
+## TiDB 的最佳适用场景
+
+简单来说,TiDB 适合具备下面这些特点的场景:
+
++ 数据量大,单机保存不下
++ 不希望做 Sharding 或者懒得做 Sharding
++ 访问模式上没有明显的热点
++ 需要事务、需要强一致、需要灾备
++ 希望 Real-Time HTAP,减少存储链路
diff --git a/br/br-monitoring-and-alert.md b/br/br-monitoring-and-alert.md
index 3e41b783c523..c7c2392f644d 100644
--- a/br/br-monitoring-and-alert.md
+++ b/br/br-monitoring-and-alert.md
@@ -25,30 +25,66 @@ summary: 了解备份恢复的监控告警。
### 监控指标
-| 指标 | 类型 | 说明 |
-|-------------------------------------------------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------------------|
-| **tikv_log_backup_interal_actor_acting_duration_sec** | Histogram | 处理内部各种消息事件的耗时。编程语言 | -驱动 | -最新已测试版本 | -支持等级 | -TiDB 适配器 | -教程 | -
---|---|---|---|---|---|
Go | -Go-MySQL-Driver | -v1.6.0 | -Full | -N/A | -使用 Go-MySQL-Driver 连接到 TiDB | -
Java | -JDBC | -8.0 | -Full | -- - | -使用 JDBC 连接到 TiDB | -
编程语言 | -ORM 框架 | -最新已测试版本 | -支持等级 | -TiDB 适配器 | -教程 | -
---|---|---|---|---|---|
Go | -gorm | -v1.23.5 | -Full | -N/A | -使用 GORM 连接到 TiDB | -
beego | -v2.0.3 | -Full | -N/A | -N/A | -|
upper/db | -v4.5.2 | -Full | -N/A | -N/A | -|
xorm | -v1.3.1 | -Full | -N/A | -N/A | -|
Java | -Hibernate | -6.1.0.Final | -Full | -N/A | -使用 Hibernate 连接到 TiDB | -
MyBatis | -v3.5.10 | -Full | -N/A | -使用 MyBatis 连接到 TiDB | -|
Spring Data JPA | -2.7.2 | -Full | -N/A | -使用 Spring Boot 连接到 TiDB | -|
jOOQ | -v3.16.7 (Open Source) | -Full | -N/A | -N/A | -|
Ruby | -Active Record | -v7.0 | -Full | -N/A | -使用 Rails 框架和 ActiveRecord ORM 连接到 TiDB | -
JavaScript / TypeScript | -Sequelize | -v6.20.1 | -Full | -N/A | -N/A | -
Prisma | -4.16.2 | -Full | -N/A | -使用 Prisma 连接到 TiDB | -|
TypeORM | -v0.3.17 | -Full | -N/A | -使用 TypeORM 连接到 TiDB | -|
Python | -Django | -v4.2 | -Full | -django-tidb | -使用 Django 连接到 TiDB | -
SQLAlchemy | -v1.4.37 | -Full | -N/A | -使用 SQLAlchemy 连接到 TiDB | -
描述 | -SQL | -
---|---|
transaction | -^SAVEPOINT |
-
skip all flush sqls | -^FLUSH |
-
table maintenance | -^OPTIMIZE\\s+TABLE |
-
^ANALYZE\\s+TABLE |
- |
^REPAIR\\s+TABLE |
- |
temporary table | -^DROP\\s+(\\/\\*\\!40005\\s+)?TEMPORARY\\s+(\\*\\/\\s+)?TABLE |
-
trigger | -^CREATE\\s+(DEFINER\\s?=.+?)?TRIGGER |
-
^DROP\\s+TRIGGER |
- |
procedure | -^DROP\\s+PROCEDURE |
-
^CREATE\\s+(DEFINER\\s?=.+?)?PROCEDURE |
- |
^ALTER\\s+PROCEDURE |
- |
view | -^CREATE\\s*(OR REPLACE)?\\s+(ALGORITHM\\s?=.+?)?(DEFINER\\s?=.+?)?\\s+(SQL SECURITY DEFINER)?VIEW |
-
^DROP\\s+VIEW |
- |
^ALTER\\s+(ALGORITHM\\s?=.+?)?(DEFINER\\s?=.+?)?(SQL SECURITY DEFINER)?VIEW |
- |
function | -^CREATE\\s+(AGGREGATE)?\\s*?FUNCTION |
-
^CREATE\\s+(DEFINER\\s?=.+?)?FUNCTION |
- |
^ALTER\\s+FUNCTION |
- |
^DROP\\s+FUNCTION |
- |
tableSpace | -^CREATE\\s+TABLESPACE |
-
^ALTER\\s+TABLESPACE |
- |
^DROP\\s+TABLESPACE |
- |
event | -^CREATE\\s+(DEFINER\\s?=.+?)?EVENT |
-
^ALTER\\s+(DEFINER\\s?=.+?)?EVENT |
- |
^DROP\\s+EVENT |
- |
account management | -^GRANT |
-
^REVOKE |
- |
^CREATE\\s+USER |
- |
^ALTER\\s+USER |
- |
^RENAME\\s+USER |
- |
^DROP\\s+USER |
- |
^DROP\\s+USER |
-
^
][operator_bitwise-xor], [<<][operator_left-shift], [>>][operator_right-shift] |
-| [比较运算](/functions-and-operators/operators.md#比较方法和操作符) | [<][operator_less-than], [<=][operator_less-than-or-equal], [=][operator_equal], [!= (<\>)][operator_not-equal], [>][operator_greater-than], [>=][operator_greater-than-or-equal], [<=>][operator_equal-to], [BETWEEN ... AND ...][operator_between], [COALESCE()][function_coalesce], [IN()][operator_in], [INTERVAL()][function_interval], [IS NOT NULL][operator_is-not-null], [IS NOT][operator_is-not], [IS NULL][operator_is-null], [IS][operator_is], [ISNULL()][function_isnull], [LIKE][operator_like], [NOT BETWEEN ... AND ...][operator_not-between], [NOT IN()][operator_not-in], [NOT LIKE][operator_not-like], [STRCMP()][function_strcmp] |
-| [数值运算](/functions-and-operators/numeric-functions-and-operators.md) | [+][operator_plus], [-][operator_minus], [*][operator_times], [/][operator_divide], [DIV][operator_div], [% (MOD)][operator_mod], [-][operator_unary-minus], [ABS()][function_abs], [ACOS()][function_acos], [ASIN()][function_asin], [ATAN()][function_atan], [ATAN2(), ATAN()][function_atan2], [CEIL()][function_ceil], [CEILING()][function_ceiling], [CONV()][function_conv], [COS()][function_cos], [COT()][function_cot], [CRC32()][function_crc32], [DEGREES()][function_degrees], [EXP()][function_exp], [FLOOR()][function_floor], [LN()][function_ln], [LOG()][function_log], [LOG10()][function_log10], [LOG2()][function_log2], [MOD()][function_mod], [PI()][function_pi], [POW()][function_pow], [POWER()][function_power], [RADIANS()][function_radians], [RAND()][function_rand], [ROUND()][function_round], [SIGN()][function_sign], [SIN()][function_sin], [SQRT()][function_sqrt] |
-| [控制流运算](/functions-and-operators/control-flow-functions.md) | [CASE][operator_case], [IF()][function_if], [IFNULL()][function_ifnull] |
-| [JSON 运算](/functions-and-operators/json-functions.md) | [JSON_ARRAY([val[, val] ...])][json_array],'a' \|\| 'b'
| `CONCAT('a','b')` | |
-| 获取字符串长度 | `LENGTH(str)` | `CHAR_LENGTH(str)` | |
-| 获取子串 | `SUBSTR('abcdefg',0,2) = 'ab'`KB\|MB\|GB
)ADMIN CHECK [TABLE\|INDEX]
](/sql-statements/sql-statement-admin-check-table-index.md) | 校验表中数据和对应索引的一致性 |
-| [ADMIN SHOW DDL [JOBS\|QUERIES]
](/sql-statements/sql-statement-admin-show-ddl.md) | 显示有关当前正在运行或最近完成的 DDL 作业的详细信息|
-| [ADMIN SHOW TELEMETRY
](/sql-statements/sql-statement-admin-show-telemetry.md) | 显示通过[遥测](/telemetry.md)功能收集到并分享给 PingCAP 的使用信息。 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+| 语句 | 功能描述 |
++=========================================================================================+======================================================================+
+| [`ADMIN CANCEL DDL JOBS`](/sql-statements/sql-statement-admin-cancel-ddl.md) | 取消当前正在运行的 DDL 作业 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+| [`ADMIN CHECKSUM TABLE`](/sql-statements/sql-statement-admin-checksum-table.md) | 计算表中所有行和索引的 CRC64 校验和 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+| [`ADMIN CHECK [TABLE|INDEX]`](/sql-statements/sql-statement-admin-check-table-index.md) | 校验表中数据和对应索引的一致性 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+| [`ADMIN SHOW DDL [JOBS|QUERIES]`](/sql-statements/sql-statement-admin-show-ddl.md) | 显示有关当前正在运行或最近完成的 DDL 作业的详细信息 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
+| [`ADMIN SHOW TELEMETRY`](/sql-statements/sql-statement-admin-show-telemetry.md) | 显示通过[遥测](/telemetry.md)功能收集到并分享给 PingCAP 的使用信息。 |
++-----------------------------------------------------------------------------------------+----------------------------------------------------------------------+
## `ADMIN RELOAD` 语句
diff --git a/sql-statements/sql-statement-show-create-database.md b/sql-statements/sql-statement-show-create-database.md
index 7c7f8b0a3207..72002cce71cb 100644
--- a/sql-statements/sql-statement-show-create-database.md
+++ b/sql-statements/sql-statement-show-create-database.md
@@ -1,70 +1,70 @@
----
-title: SHOW CREATE DATABASE
-summary: TiDB 数据库中 SHOW CREATE DATABASE 的使用概况。
----
-
-# SHOW CREATE DATABASE
-
-`SHOW CREATE DATABASE` 语句用于显示用 SQL 重新创建已有库的确切语句。`SHOW CREATE SCHEMA` 与其同义。
-
-## 语法图
-
-**ShowCreateDatabaseStmt:**
-
-```ebnf+diagram
-ShowCreateDatabaseStmt ::=
- "SHOW" "CREATE" "DATABASE" | "SCHEMA" ("IF" "NOT" "EXISTS")? DBName
-```
-
-## 示例
-
-{{< copyable "sql" >}}
-
-```sql
-CREATE DATABASE test;
-```
-
-```
-Query OK, 0 rows affected (0.12 sec)
-```
-
-{{< copyable "sql" >}}
-
-```sql
-SHOW CREATE DATABASE test;
-```
-
-```
-+----------+------------------------------------------------------------------+
-| Database | Create Database |
-+----------+------------------------------------------------------------------+
-| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
-+----------+------------------------------------------------------------------+
-1 row in set (0.00 sec)
-```
-
-{{< copyable "sql" >}}
-
-```sql
-SHOW CREATE SCHEMA IF NOT EXISTS test;
-```
-
-```
-+----------+-------------------------------------------------------------------------------------------+
-| Database | Create Database |
-+----------+-------------------------------------------------------------------------------------------+
-| test | CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
-+----------+-------------------------------------------------------------------------------------------+
-1 row in set (0.00 sec)
-```
-
-## MySQL 兼容性
-
-`SHOW CREATE DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请在 GitHub 上提交 [issue](https://github.com/pingcap/tidb/issues/new/choose)。
-
-## 另请参阅
-
-* [CREATE TABLE](/sql-statements/sql-statement-create-table.md)
-* [DROP TABLE](/sql-statements/sql-statement-drop-table.md)
-* [SHOW TABLES](/sql-statements/sql-statement-show-tables.md)
-* [SHOW COLUMNS FROM](/sql-statements/sql-statement-show-columns-from.md)
+---
+title: SHOW CREATE DATABASE
+summary: TiDB 数据库中 SHOW CREATE DATABASE 的使用概况。
+---
+
+# SHOW CREATE DATABASE
+
+`SHOW CREATE DATABASE` 语句用于显示用 SQL 重新创建已有库的确切语句。`SHOW CREATE SCHEMA` 与其同义。
+
+## 语法图
+
+**ShowCreateDatabaseStmt:**
+
+```ebnf+diagram
+ShowCreateDatabaseStmt ::=
+ "SHOW" "CREATE" "DATABASE" | "SCHEMA" ("IF" "NOT" "EXISTS")? DBName
+```
+
+## 示例
+
+{{< copyable "sql" >}}
+
+```sql
+CREATE DATABASE test;
+```
+
+```
+Query OK, 0 rows affected (0.12 sec)
+```
+
+{{< copyable "sql" >}}
+
+```sql
+SHOW CREATE DATABASE test;
+```
+
+```
++----------+------------------------------------------------------------------+
+| Database | Create Database |
++----------+------------------------------------------------------------------+
+| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
++----------+------------------------------------------------------------------+
+1 row in set (0.00 sec)
+```
+
+{{< copyable "sql" >}}
+
+```sql
+SHOW CREATE SCHEMA IF NOT EXISTS test;
+```
+
+```
++----------+-------------------------------------------------------------------------------------------+
+| Database | Create Database |
++----------+-------------------------------------------------------------------------------------------+
+| test | CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
++----------+-------------------------------------------------------------------------------------------+
+1 row in set (0.00 sec)
+```
+
+## MySQL 兼容性
+
+`SHOW CREATE DATABASE` 语句与 MySQL 完全兼容。如发现任何兼容性差异,请在 GitHub 上提交 [issue](https://github.com/pingcap/tidb/issues/new/choose)。
+
+## 另请参阅
+
+* [CREATE TABLE](/sql-statements/sql-statement-create-table.md)
+* [DROP TABLE](/sql-statements/sql-statement-drop-table.md)
+* [SHOW TABLES](/sql-statements/sql-statement-show-tables.md)
+* [SHOW COLUMNS FROM](/sql-statements/sql-statement-show-columns-from.md)
diff --git a/ticdc-deployment-topology.md b/ticdc-deployment-topology.md
index 8bddfac001c3..e6c21b137763 100644
--- a/ticdc-deployment-topology.md
+++ b/ticdc-deployment-topology.md
@@ -13,13 +13,28 @@ summary: 介绍 TiCDC 部署 TiDB 集群的拓扑结构。
## 拓扑信息
-|实例 | 个数 | 物理机配置 | IP |配置 |
-| :-- | :-- | :-- | :-- | :-- |
-| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1 \${db_name}.\${table_name}.\${csv\|sql\|parquet}
|
-|数据文件| 如果一个表分布于多个数据文件,这些文件命名需加上文件编号的后缀 | \${db_name}.\${table_name}.001.\${csv\|sql\|parquet}
|
-|压缩文件| 上述所有类型文件如带压缩文件名后缀,如 `gzip`、`snappy` 或 `zstd`,TiDB Lightning 会流式解压后进行导入 | \${db_name}.\${table_name}.\${csv\|sql\|parquet}.{compress}
|
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+| 文件类型 | 分类 | 命名规则 |
++:============+:=======================================================================================================+:=========================================================+
+| Schema 文件 | 包含 DDL 语句 `CREATE TABLE` 的文件 | `${db_name}.${table_name}-schema.sql` |
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+| Schema 文件 | 包含 `CREATE DATABASE` DDL 语句的文件 | `${db_name}-schema-create.sql` |
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+| 数据文件 | 包含整张表的数据文件,该文件会被导入 `${db_name}.${table_name}` 表 | `${db_name}.${table_name}.${csv|sql|parquet}` |
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+| 数据文件 | 如果一个表分布于多个数据文件,这些文件命名需加上文件编号的后缀 | `${db_name}.${table_name}.001.${csv|sql|parquet}` |
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
+| 压缩文件 | 上述所有类型文件如带压缩文件名后缀,如 `gzip`、`snappy` 或 `zstd`,TiDB Lightning 会流式解压后进行导入 | `${db_name}.${table_name}.${csv|sql|parquet}.{compress}` |
++-------------+--------------------------------------------------------------------------------------------------------+----------------------------------------------------------+
TiDB Lightning 尽量并行处理数据,由于文件必须顺序读取,所以数据处理协程是文件级别的并发(通过 `region-concurrency` 配置控制)。因此导入大文件时性能比较差。通常建议单个文件尺寸为 256MiB,以获得最好的性能。
diff --git a/tidb-lightning/tidb-lightning-requirements.md b/tidb-lightning/tidb-lightning-requirements.md
index 11d46943d272..d30f27fe1ed1 100644
--- a/tidb-lightning/tidb-lightning-requirements.md
+++ b/tidb-lightning/tidb-lightning-requirements.md
@@ -11,71 +11,27 @@ summary: 了解 TiDB Lightning 运行时对目标数据库的必需条件。
TiDB Lightning 导入数据时,根据导入方式和启用特性等,需要下游数据库用户具备不同的权限,可参考下表:
-- | 特性 | -作用域 | -所需权限 | -备注 | -
必需 | -基本功能 | -目标 table | -CREATE,SELECT,INSERT,UPDATE,DELETE,DROP,ALTER | -DROP 仅 tidb-lightning-ctl 在执行 checkpoint-destroy-all 时需要 | -
目标 database | -CREATE | -- | ||
必需 | -Logical Import Mode | -information_schema.columns | -SELECT | -- |
Physical Import Mode | -mysql.tidb | -SELECT | -- | |
- | -SUPER | -- | ||
- | -RESTRICTED_VARIABLES_ADMIN,RESTRICTED_TABLES_ADMIN | -当目标 TiDB 开启 SEM | -||
推荐 | -冲突检测,max-error | -lightning.task-info-schema-name 配置的 schema | -SELECT,INSERT,UPDATE,DELETE,CREATE,DROP | -如不需要,该值必须设为"" | -
可选 | -并行导入 | -lightning.meta-schema-name 配置的 schema | -SELECT,INSERT,UPDATE,DELETE,CREATE,DROP | -如不需要,该值必须设为"" | -
可选 | -checkpoint.driver = "mysql" | -checkpoint.schema 设置 | -SELECT,INSERT,UPDATE,DELETE,CREATE,DROP | -使用数据库而非文件形式存放 checkpoint 信息时需要 | -
\|
(bitor), `~` (bitneg), `^` (bitxor) |
-| [字符串函数](/functions-and-operators/string-functions.md) | `SUBSTR()`, `CHAR_LENGTH()`, `REPLACE()`, `CONCAT()`, `CONCAT_WS()`, `LEFT()`, `RIGHT()`, `ASCII()`, `LENGTH()`, `TRIM()`, `LTRIM()`, `RTRIM()`, `POSITION()`, `FORMAT()`, `LOWER()`, `UCASE()`, `UPPER()`, `SUBSTRING_INDEX()`, `LPAD()`, `RPAD()`, `STRCMP()` |
-| [正则函数和算子](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()` |
-| [日期函数](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`, `TIMESTAMPDIFF()`, `FROM_UNIXTIME()`, `UNIX_TIMESTAMP(int)`, `UNIX_TIMESTAMP(decimal)`, `STR_TO_DATE(date)`, `STR_TO_DATE(datetime)`, `DATEDIFF()`, `YEAR()`, `MONTH()`, `DAY()`, `EXTRACT(datetime)`, `DATE()`, `HOUR()`, `MICROSECOND()`, `MINUTE()`, `SECOND()`, `SYSDATE()`, `DATE_ADD/ADDDATE(datetime, int)`, `DATE_ADD/ADDDATE(string, int/real)`, `DATE_SUB/SUBDATE(datetime, int)`, `DATE_SUB/SUBDATE(string, int/real)`, `QUARTER()`, `DAYNAME()`, `DAYOFMONTH()`, `DAYOFWEEK()`, `DAYOFYEAR()`, `LAST_DAY()`, `MONTHNAME()`, `TO_SECONDS()`, `TO_DAYS()`, `FROM_DAYS()`, `WEEKOFYEAR()`
-| [JSON 函数](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`, `->`, `->>`, `JSON_EXTRACT()` |
-| [转换函数](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)` |
-| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md) | `MIN()`, `MAX()`, `SUM()`, `COUNT()`, `AVG()`, `APPROX_COUNT_DISTINCT()`, `GROUP_CONCAT()` |
-| [其他函数](/functions-and-operators/miscellaneous-functions.md) | `INET_NTOA()`, `INET_ATON()`, `INET6_NTOA()`, `INET6_ATON()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| 表达式类型 | 运算 |
++:==============================================================================================================+:====================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================+
+| [数学函数](/functions-and-operators/numeric-functions-and-operators.md) | `+`, `-`, `/`, `*`, `%`, `>=`, `<=`, `=`, `!=`, `<`, `>`, `ROUND()`, `ABS()`, `FLOOR(int)`, `CEIL(int)`, `CEILING(int)`, `SQRT()`, `LOG()`, `LOG2()`, `LOG10()`, `LN()`, `EXP()`, `POW()`, `SIGN()`, `RADIANS()`, `DEGREES()`, `CONV()`, `CRC32()`, `GREATEST(int/real)`, `LEAST(int/real)` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [逻辑函数](/functions-and-operators/control-flow-functions.md)和[算子](/functions-and-operators/operators.md) | `AND`, `OR`, `NOT`, `CASE WHEN`, `IF()`, `IFNULL()`, `ISNULL()`, `IN`, `LIKE`, `COALESCE`, `IS` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [位运算](/functions-and-operators/bit-functions-and-operators.md) | `&` (bitand), `|` (bitor), `~` (bitneg), `^` (bitxor) |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [字符串函数](/functions-and-operators/string-functions.md) | `SUBSTR()`, `CHAR_LENGTH()`, `REPLACE()`, `CONCAT()`, `CONCAT_WS()`, `LEFT()`, `RIGHT()`, `ASCII()`, `LENGTH()`, `TRIM()`, `LTRIM()`, `RTRIM()`, `POSITION()`, `FORMAT()`, `LOWER()`, `UCASE()`, `UPPER()`, `SUBSTRING_INDEX()`, `LPAD()`, `RPAD()`, `STRCMP()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [正则函数和算子](/functions-and-operators/string-functions.md) | `REGEXP`, `REGEXP_LIKE()`, `REGEXP_INSTR()`, `REGEXP_SUBSTR()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [日期函数](/functions-and-operators/date-and-time-functions.md) | `DATE_FORMAT()`, `TIMESTAMPDIFF()`, `FROM_UNIXTIME()`, `UNIX_TIMESTAMP(int)`, `UNIX_TIMESTAMP(decimal)`, `STR_TO_DATE(date)`, `STR_TO_DATE(datetime)`, `DATEDIFF()`, `YEAR()`, `MONTH()`, `DAY()`, `EXTRACT(datetime)`, `DATE()`, `HOUR()`, `MICROSECOND()`, `MINUTE()`, `SECOND()`, `SYSDATE()`, `DATE_ADD/ADDDATE(datetime, int)`, `DATE_ADD/ADDDATE(string, int/real)`, `DATE_SUB/SUBDATE(datetime, int)`, `DATE_SUB/SUBDATE(string, int/real)`, `QUARTER()`, `DAYNAME()`, `DAYOFMONTH()`, `DAYOFWEEK()`, `DAYOFYEAR()`, `LAST_DAY()`, `MONTHNAME()`, `TO_SECONDS()`, `TO_DAYS()`, `FROM_DAYS()`, `WEEKOFYEAR()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [JSON 函数](/functions-and-operators/json-functions.md) | `JSON_LENGTH()`, `->`, `->>`, `JSON_EXTRACT()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [转换函数](/functions-and-operators/cast-functions-and-operators.md) | `CAST(int AS DOUBLE), CAST(int AS DECIMAL)`, `CAST(int AS STRING)`, `CAST(int AS TIME)`, `CAST(double AS INT)`, `CAST(double AS DECIMAL)`, `CAST(double AS STRING)`, `CAST(double AS TIME)`, `CAST(string AS INT)`, `CAST(string AS DOUBLE), CAST(string AS DECIMAL)`, `CAST(string AS TIME)`, `CAST(decimal AS INT)`, `CAST(decimal AS STRING)`, `CAST(decimal AS TIME)`, `CAST(time AS INT)`, `CAST(time AS DECIMAL)`, `CAST(time AS STRING)`, `CAST(time AS REAL)` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [聚合函数](/functions-and-operators/aggregate-group-by-functions.md) | `MIN()`, `MAX()`, `SUM()`, `COUNT()`, `AVG()`, `APPROX_COUNT_DISTINCT()`, `GROUP_CONCAT()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
+| [其他函数](/functions-and-operators/miscellaneous-functions.md) | `INET_NTOA()`, `INET_ATON()`, `INET6_NTOA()`, `INET6_ATON()` |
++---------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
## 下推限制
diff --git a/tispark-deployment-topology.md b/tispark-deployment-topology.md
index 106546fabe50..e317461c9026 100644
--- a/tispark-deployment-topology.md
+++ b/tispark-deployment-topology.md
@@ -15,13 +15,28 @@ summary: 介绍 TiUP 部署包含 TiSpark 组件的 TiDB 集群的拓扑结构
## 拓扑信息
-|实例 | 个数 | 物理机配置 | IP |配置 |
-| :-- | :-- | :-- | :-- | :-- |
-| TiDB |3 | 16 VCore 32GB * 1 | 10.0.1.1