---
title: '一名开发者眼中的 TiDB 与 MySQL 的选择丨TiDB Community'
date: '2023-05-19T00:00:00+08:00'
status: publish
permalink: /blog/choice-between-tidb-and-mysql
author:
    - 谭新宇
    - 大数据模型
excerpt: '随着 MySQL 8.0 的发布和即将到来的 5.7 版本的停止支持，许多 MySQL 用户正面临升级和转型的抉择。本文为 TiDB 社区用户撰写，以一名开发者的视角，深入探讨和比较了 TiDB 和 MySQL 的差异。'
type: post
id: 3229
category:
    - 案例实践
tag:
    - MySQL
    - TiDB
post_format: []
profile:
    - 大数据模型
algolia_posts_post_records_count:
    - '6'
---
> 本文作者：大数据模型。对制造业、银行业、通讯业了解多一点，关心专注国产数据库技术布道以及数据资产建设的应用实践。

导读
--

随着 MySQL 8.0 的发布和即将到来的 5.7 版本的停止支持，许多 MySQL 用户正面临升级和转型的抉择。本文为 TiDB 社区用户撰写，以一名开发者的视角，深入探讨和比较了 TiDB 和 MySQL 的差异。希望通过本文，能为读者在架构选型方面提供一些帮助和指导。

TiDB 在墨天轮国产数据库排行榜中长年位列前茅，社区活跃度高且人气旺盛。那么 TiDB 使用场景相似产品中，有哪些比较优秀呢？我认为其中一个是 MySQL——毕竟在中国，MySQL 早已深入人心，并且工程师们能够轻松地运用它。

TiDB 与 MySQL 的对比
----------------

有些人直接将 TiDB 称为"大号的 MySQL"，但实际情况并非如此。为了使工程师们能够像使用 MySQL 一样使用 TiDB，TiDB 在接口层进行了大量的改进。它在语法、表名、引用甚至元数据等方面尽量与 MySQL 保持一致，但是实际执行的每个语句背后都有不同的数据流程和服务流向。因此，尽管在表面上它们相似，但其背后的数据处理和服务机制是不同的。

**类型方面**，MySQL 是纯粹单机式数据库，TiDB 则是分布式数据库。TiDB 能够方便自由地增加节点来扩展存算能力，而 MySQL 则需要通过定向策略，如中间件路由或读写分离等方式来增加节点以提升性能，这使得 MySQL 的扩展性相对受限且相对僵化。

**引擎方面**，MySQL 拥有多个引擎选项，如 MyISAM、InnoDB、Memory 等，并且可以通过插件支持更多的引擎，如 RocksDB 和 HandlerSocket 等。而 TiDB 虽然只有两个引擎选项，但却能够应对各种应用场景的需求。

**架构方面** ， MySQL 是偏紧密耦合，分为接口层、服务层、存储层三个层次。接口层负责请求处理、授权认证和安全性，服务层负责查询解析、分析、优化、缓存和系统内置函数，存储层负责数据的存储和处理，所有这些组件都在一个服务进程中统一运行。**而 TiDB 采用松散耦合的架构，将数据库的关键组件进行抽象，并根据其分布式特性划分为计算层、存储层和协调层**。

- TiDB 计算层类似 MySQL 的接口层，负责接收 SQL 请求，处理 SQL 相关的逻辑，并通过协调层找到存储层数据的位置。它与存储层进行交互以获取数据，并最终返回结果。
- TiDB 的存储层负责数据的存储，其存储容量没有上限。通常情况下，存储层会为同一份数据维护 3 个副本；以满足高并发需求。协调层会对存储层中的数据进行负载均衡的处理。
- TiDB 的协调层是集群的管理模块，其主要工作包括三个方面：管理集群的元信息、调度和负载均衡存储层的数据，以及分配全局唯一且递增的事务 ID。

**数据处理技术上**，MySQL 是 **B+树**的组织存储结构，B+树适合读多写少，如果写多了，写的影响动作主要是插入、删除，会导致全局的平衡树下面的页频繁分裂或者合并，直接影响性能，影响读放大。TiDB 是 **LSM** 树的组织存储结构，擅长写多读少，如果读多了，在内存扫描不到数据，就会去硬盘里面去寻找无序的 sst 文件，所以数据越多越大就会读放大。

**处理存储上**，MySQL 类似微内核，微内核架构由核心服务和插件模块组成，核心服务负责请求后处理机制流程并进行优化，插件模块主要用来放置 置处理存储的引擎，引擎决定性能上限， 微内核的插件式对开发者友好，可以自由扩展，所以 MySQL 派生了 infobright、MyRocks 等第三方相关引擎，TiDB 的核心服务分散在 TiDB 模块和 PD 模块里面，两者协同工作构成请求解析、处理、优化及其它服务功能 ， TiKV 模块和 TiFlash 模块则是引擎。无论是顺序读写还是随机读写，核心服务协同背端的引擎工作串成整个数据全链条过程，MySQL 是在单机单进程的内部去完成这个过程的，而 TiDB 是分布式多进程完成这个过程的。

**产品方面**，MySQL 默认使用 InnoDB 引擎，擅长处理 OLTP 的业务场景。同时，MySQL 还支持插件组装各种引擎，使其成为一个通用型的数据库产品，适用于各种业务场景。而 TiDB 默认采用悲观事务的方式，同样专注于 OLTP，也是一个通用型的数据库产品。然而，这两者之间存在一些差异。由于 MySQL 是单机型结构，如果需要进行扩展，只能通过数据库中间件路由的方式进行划分。而如果数据已满，就需要停机或停服，重新进行数据的分割。

TiDB 具有对业务的无侵入性，且扩展非常简单。在其发展至今，安装和维护方面已经非常成熟。通过 TiUP 工具，可以轻松进行分布式集群的组装和维护操作，并且支持在线升级和无缝迁移。这使得使用 TiDB 的过程更加便捷和高效，使用户能够更好地管理和运维他们的分布式数据库系统。

综上所述，TiDB 与 MySQL 属于不同类型的数据产品，并不能直接进行对比。然而，从数据库的特性和市场趋势的角度来看，它们可以有一些维度上的对比指标。事实上，TiDB 致力于向 MySQL 学习，并且还聘请了 InnoDB 的核心开发工程师，致力于调整 TiDB 的底盘，使其在内部和外部都更像 MySQL。

同类竞争产品
------

TiDB 是一款**分布式数据库产品**，它以分布式为标识并能基于线下安装，在国内外都有类似的产品。那么 TiDB 与其他产品有什么不同？参照数据库处理的流程，我将从任务开始到任务结束来详述。

1. 用户发起请求：数据库客户端向指定的数据库集群发起请求。
2. 目标数据库响应：数据库集群的指定节点响应用户的请求。
3. 两者建立会话：数据库集群其中一个节点与客户端产生会话。
4. 对象请求解析 ：数据库对接收到的请求进行语法检查、对象解析，并将其转换为对应的关系代数结构，然后进行计划任务优化。
5. 调度并且执行：寻找最合适的副本，根据优先级进行，是内存、缓存、数据快照、存储等等。
6. 监测任务状态：数据库监测执行中任务的状态。
7. 返回数据结果：数据库服务端将执行结果返回给数据库客户端。

上述环节中，最关键的是第 2 步、第 4 步和第 5 步。

第 2 步是 哪一个节点响应数据库客户的请求，分布式数据库有两种系统架构，一种是中心化架构【master\\slave】，一种是去中心化架构。中心化架构的负色职责分清，负责干活、负责指挥、负责接待用户，而去中心化架构则是每个节点角色平等，对待客户的请求，其中的一个节点会瞬间切换成负责接待，剩余的节点根据情况转化执行。

TiDB 在这里采用中心化的架构，节点角色之间的职责更加清晰，分工更加明确。

第 4 步和第 5 步是数据计算和数据存储的关键步骤，TiDB 在这里做了深度的松散解耦，数据计算用 TiDB，数据存储用 TiKV，两者是真正意义上的存算分离，要增加存储容量，可以增加没有 CPU 的硬盘服务器，要增加计算能力，可以增加没有硬盘的服务器。关于分布式的功能和作用则集中在一个 PD 的模块上。

采用集中式的分布式架构的产品则采用了去中心架构，而且计算和存储高度耦合，又称为单机式的分布式架构。

TiDB 比起同类产品在架构上更加高度松散耦合，与云计算技术更加紧密协作，珠联璧合。

TiDB vs MySQL
-------------

如果 TiDB 要做大做强，必须要撼动广大开发人员的工作使用习惯。大部分开发人员已经十分熟悉并广泛使用 MySQL，无论是在 TP 应用还是 AP 应用中。不论性能如何，他们首先会选择 MySQL 来开发业务代码。这也意味着 MySQL 经常被用作 HTAP 数据库。接下来，我将使用 CH-benchmark 来对 TiDB 6.0 和 MySQL 8.0 进行一项测试。

**TPC-CH 由未经修改的 TPC-C 模型和事务、以及 TPC-H 查询的改编版本构成，TPC-CH 保持所有 TPC-C 实体和关系完全不变**，并集成了 TPC-H 模型中的 SUPPLIER、REGION 和 NATION 表。这些表在 TPC-H 查询中频繁使用，并允许以非侵入的方式集成到 TPC-C 模型中。SUPPLIER 包含固定数量（10,000 条）的条目。因此，STOCK 中的一条记录可以通过 STOCK.S I ID × STOCK.S W ID mod 10, 000 = SUPPLIER.SU SUPPKEY 与其唯一的供应商（SUPPLIER 表中对应记录）关联起来。TPC-C 中的原始 CUSTOMER 表不包含引用自 NATION 表的外键。我们并没有改变原始模型，从而保持了与现有 TPC-C 的兼容性，所以外键是从字段 C STATE 的第一个字符开始计算的。TPC-C 规定第一个字符可以有 62 个不同的值（即大写字母、小写字母、数字），因此我们选择了 62 个国家来填充 NATION。根据 TPC-H 规范，主键 N NATIONKEY 是一个标识符。它的值被规定，从而使得与这些值相关联的 ASCII 值是一个字母或数字,即 N NATIONKEY ∈ \[48, 57\]∪\[65, 90\]∪\[97. 122\]。因此，不需要额外的计算来跳过 ASCII 码中数字、大写字母和小写字母之间的间隔。不支持从字符转换到 ASCII 码的数据库系统可能会偏离 TPC-H 模式，使用单个字符作为 NATION 的主键。REGION 包含国家的五个地区。新表之间的关系使用简单的外键字段来建模：NATION.N REGIONKEY 和 SUPPLIER.SU NATIONKEY。

**在 CH-Benchmark 中结合了 TPC-C 和 TPC-H 两种基准**，它把原来 TPC-C 中的 9 个表和 TPC-H 中的 8 个表修改合并成了 12 个表，并将两者的伸缩模型也统一起来（Scaling TPC-H by the same factors of TPC-C）。

### 测试环境

#### 硬件配置

|---|
|-----|
|  | CPU |  | 8 核 Intel(R) Xeon(R) |  |
|  | 内存 |  | 16 |  |

#### 测试配置

|---|
|-----|
|  | MySQL 8.0 |  | 192.168.1.X |  | MySQL 单机 |  |
|  | TiDB 6.0 |  | 192.168.1.X |  | TiDB 单机 |  |
|  | CH-benchmark |  | 192.168.2.X |  | HTAP 测试工具，生成数据 |  |
|  | TiUP Bench |  | 192.168.2.X |  | HTAP 测试工具，进行测试 |  |

生成数据
----

在我的实验中，我使用了 TiDB Bench 对数据进行了压测，生成这些数据的工具是 CH-benchmark。

**安装 CH-benchmark**

```
https://github.com/DASLab-IDA/CH-benchmark
-rwxr-xr-x. 1 root root 1007440 Mar 29 16:13 chBenchmark
-rw-r--r--. 1 root root   12745 Mar  3  2022 chBenchmark.cpp
-rw-r--r--. 1 root root  194096 Mar 29 16:13 chBenchmark.o
-rw-r--r--. 1 root root     561 Mar  3  2022 LICENSE
-rw-r--r--. 1 root root    1167 Mar  3  2022 Makefile
-rw-r--r--. 1 root root    2650 Mar  3  2022 README.md
drwxr-xr-x. 3 root root    4096 Mar 29 16:13 src
[root@hdp1 CH-benchmark-main]# make

运行make之后会就对当天的文件进行编译，生成chBenchmark 执行命令

chBenchmark命令如下
Create initial database as CSV files:
    chBenchmark
    -csv
    -wh <WAREHOUSE_COUNT>
    -pa <INITIAL_DB_GEN_PATH>

    example: chBenchmark -csv -wh 50 -pa /path/to/any/directory

生成数据如下,生成一个warehouse的数据

chBenchmark -csv -wh 1 -pa  /tmp/chBenchmark1
```

### 建表语句

```
CREATE TABLE `customer` (
  `c_id` int NOT NULL,
  `c_d_id` int NOT NULL,
  `c_w_id` int NOT NULL,
  `c_first` varchar(16) DEFAULT NULL,
  `c_middle` char(2) DEFAULT NULL,
  `c_last` varchar(16) DEFAULT NULL,
  `c_street_1` varchar(20) DEFAULT NULL,
  `c_street_2` varchar(20) DEFAULT NULL,
  `c_city` varchar(20) DEFAULT NULL,
  `c_state` char(2) DEFAULT NULL,
  `c_zip` char(9) DEFAULT NULL,
  `c_phone` char(16) DEFAULT NULL,
  `c_since` datetime DEFAULT NULL,
  `c_credit` char(2) DEFAULT NULL,
  `c_credit_lim` decimal(12,2) DEFAULT NULL,
  `c_discount` decimal(4,4) DEFAULT NULL,
  `c_balance` decimal(12,2) DEFAULT NULL,
  `c_ytd_payment` decimal(12,2) DEFAULT NULL,
  `c_payment_cnt` int DEFAULT NULL,
  `c_delivery_cnt` int DEFAULT NULL,
  `c_data` varchar(500) DEFAULT NULL,
  PRIMARY KEY (`c_w_id`,`c_d_id`,`c_id`),
  KEY `idx_customer` (`c_w_id`,`c_d_id`,`c_last`,`c_first`)
);

CREATE TABLE `district` (
  `d_id` int NOT NULL,
  `d_w_id` int NOT NULL,
  `d_name` varchar(10) DEFAULT NULL,
  `d_street_1` varchar(20) DEFAULT NULL,
  `d_street_2` varchar(20) DEFAULT NULL,
  `d_city` varchar(20) DEFAULT NULL,
  `d_state` char(2) DEFAULT NULL,
  `d_zip` char(9) DEFAULT NULL,
  `d_tax` decimal(4,4) DEFAULT NULL,
  `d_ytd` decimal(12,2) DEFAULT NULL,
  `d_next_o_id` int DEFAULT NULL,
  PRIMARY KEY (`d_w_id`,`d_id`)
);

CREATE TABLE `history` (
  `h_c_id` int NOT NULL,
  `h_c_d_id` int NOT NULL,
  `h_c_w_id` int NOT NULL,
  `h_d_id` int NOT NULL,
  `h_w_id` int NOT NULL,
  `h_date` datetime DEFAULT NULL,
  `h_amount` decimal(6,2) DEFAULT NULL,
  `h_data` varchar(24) DEFAULT NULL,
  KEY `idx_h_w_id` (`h_w_id`),
  KEY `idx_h_c_w_id` (`h_c_w_id`)
);

CREATE TABLE `item` (
  `i_id` int NOT NULL,
  `i_im_id` int DEFAULT NULL,
  `i_name` varchar(24) DEFAULT NULL,
  `i_price` decimal(5,2) DEFAULT NULL,
  `i_data` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`i_id`)
);

CREATE TABLE `nation` (
  `n_nationkey` tinyint NOT NULL,
  `n_name` char(25) NOT NULL,
  `n_regionkey` tinyint NOT NULL,
  `n_comment` char(152) NOT NULL,
  PRIMARY KEY (`n_nationkey`)
);

CREATE TABLE `new_order` (
  `no_o_id` int NOT NULL,
  `no_d_id` int NOT NULL,
  `no_w_id` int NOT NULL,
  PRIMARY KEY (`no_w_id`,`no_d_id`,`no_o_id`)
);

CREATE TABLE `orderline` (
  `ol_o_id` int NOT NULL,
  `ol_d_id` tinyint NOT NULL,
  `ol_w_id` int NOT NULL,
  `ol_number` tinyint NOT NULL,
  `ol_i_id` int DEFAULT NULL,
  `ol_supply_w_id` int DEFAULT NULL,
  `ol_delivery_d` date DEFAULT NULL,
  `ol_quantity` smallint DEFAULT NULL,
  `ol_amount` decimal(6,2) DEFAULT NULL,
  `ol_dist_info` char(24) DEFAULT NULL,
  PRIMARY KEY (`ol_w_id`,`ol_d_id`,`ol_o_id`,`ol_number`),
  KEY `fk_orderline_order` (`ol_w_id`,`ol_d_id`,`ol_o_id`),
  KEY `fk_orderline_stock` (`ol_supply_w_id`,`ol_i_id`)
);

CREATE TABLE `orders` (
  `o_id` int NOT NULL,
  `o_d_id` int NOT NULL,
  `o_w_id` int NOT NULL,
  `o_c_id` int DEFAULT NULL,
  `o_entry_d` datetime DEFAULT NULL,
  `o_carrier_id` int DEFAULT NULL,
  `o_ol_cnt` int DEFAULT NULL,
  `o_all_local` int DEFAULT NULL,
  PRIMARY KEY (`o_w_id`,`o_d_id`,`o_id`),
  KEY `idx_order` (`o_w_id`,`o_d_id`,`o_c_id`,`o_id`)
);

 CREATE TABLE `region` (
  `r_regionkey` tinyint NOT NULL,
  `r_name` char(55) NOT NULL,
  `r_comment` char(152) NOT NULL,
  PRIMARY KEY (`r_regionkey`)
);

CREATE TABLE `stock` (
  `s_i_id` int NOT NULL,
  `s_w_id` int NOT NULL,
  `s_quantity` int DEFAULT NULL,
  `s_dist_01` char(24) DEFAULT NULL,
  `s_dist_02` char(24) DEFAULT NULL,
  `s_dist_03` char(24) DEFAULT NULL,
  `s_dist_04` char(24) DEFAULT NULL,
  `s_dist_05` char(24) DEFAULT NULL,
  `s_dist_06` char(24) DEFAULT NULL,
  `s_dist_07` char(24) DEFAULT NULL,
  `s_dist_08` char(24) DEFAULT NULL,
  `s_dist_09` char(24) DEFAULT NULL,
  `s_dist_10` char(24) DEFAULT NULL,
  `s_ytd` int DEFAULT NULL,
  `s_order_cnt` int DEFAULT NULL,
  `s_remote_cnt` int DEFAULT NULL,
  `s_data` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`s_w_id`,`s_i_id`)
) ;

CREATE TABLE `supplier` (
  `s_suppkey` smallint NOT NULL,
  `s_name` char(25) NOT NULL,
  `s_address` char(40) NOT NULL,
  `s_nationkey` tinyint NOT NULL,
  `s_phone` char(15) NOT NULL,
  `s_acctbal` decimal(12,2) NOT NULL,
  `s_comment` char(101) NOT NULL,
  PRIMARY KEY (`s_suppkey`)
);

CREATE TABLE `warehouse` (
  `w_id` int NOT NULL,
  `w_name` varchar(10) DEFAULT NULL,
  `w_street_1` varchar(20) DEFAULT NULL,
  `w_street_2` varchar(20) DEFAULT NULL,
  `w_city` varchar(20) DEFAULT NULL,
  `w_state` char(2) DEFAULT NULL,
  `w_zip` char(9) DEFAULT NULL,
  `w_tax` decimal(4,4) DEFAULT NULL,
  `w_ytd` decimal(12,2) DEFAULT NULL,
  PRIMARY KEY (`w_id`)
);
```

### 导入数据

```
导入数据前，注意要对tidb运行以下命令

ALTER DATABASE tpcch SET tiflash replica 1;

mysql> SELECT * FROM information_schema.tiflash_replica WHERE TABLE_SCHEMA = 'tpcch';
+--------------+------------+----------+---------------+-----------------+-----------+----------+
| TABLE_SCHEMA | TABLE_NAME | TABLE_ID | REPLICA_COUNT | LOCATION_LABELS | AVAILABLE | PROGRESS |
+--------------+------------+----------+---------------+-----------------+-----------+----------+
| tpcch        | customer   |       90 |             1 |                 |         0 |        0 |
| tpcch        | district   |       93 |             1 |                 |         0 |        0 |
| tpcch        | history    |       96 |             1 |                 |         0 |        0 |
| tpcch        | item       |       99 |             1 |                 |         0 |        0 |
| tpcch        | nation     |      102 |             1 |                 |         0 |        0 |
| tpcch        | new_order  |      105 |             1 |                 |         0 |        0 |
| tpcch        | neworder   |      108 |             1 |                 |         0 |        0 |
| tpcch        | order      |      111 |             1 |                 |         0 |        0 |
| tpcch        | order_line |      113 |             1 |                 |         0 |        0 |
| tpcch        | orderline  |      115 |             1 |                 |         0 |        0 |
| tpcch        | orders     |      117 |             1 |                 |         0 |        0 |
| tpcch        | region     |      119 |             1 |                 |         0 |        0 |
| tpcch        | stock      |      121 |             1 |                 |         0 |        0 |
| tpcch        | warehouse  |      125 |             1 |                 |         0 |        0 |
| tpcch        | supplier   |      128 |             1 |                 |         0 |        0 |
+--------------+------------+----------+---------------+-----------------+-----------+----------+
15 rows in set (0.00 sec)

LOAD DATA local INFILE   '/tmp/chBenchmark1/CUSTOMER.tbl' INTO TABLE tpcch.customer   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/DISTRICT.tbl' INTO TABLE tpcch.district   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/HISTORY.tbl' INTO TABLE tpcch.history   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/ITEM.tbl' INTO TABLE tpcch.item   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/NATION.tbl' INTO TABLE tpcch.nation   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/NEWORDER.tbl' INTO TABLE tpcch.new_order   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/ORDER.tbl' INTO TABLE tpcch.orders   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/ORDERLINE.tbl' INTO TABLE tpcch.orderline   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/REGION.tbl' INTO TABLE tpcch.region   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/STOCK.tbl' INTO TABLE tpcch.stock   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/SUPPLIER.tbl' INTO TABLE tpcch.supplier   FIELDS TERMINATED BY '|';     
LOAD DATA local INFILE   '/tmp/chBenchmark1/WAREHOUSE.tbl' INTO TABLE tpcch.warehouse   FIELDS TERMINATED BY '|';    
```

### 运行压测命令

192.168.2.x上面安装tiup bench

```
tiup install bench
持续对TIDB的数据库tpcch发起50个TP并发量，并进行一次AP的21个语句查询
tiup bench ch --host 192.168.1.x  -Uhenley  -pxxxxxx -P4000 --warehouses 1 run -D tpcch -T 50 -t 1 --time 1m

持续对mysql的数据库tpcch发起50个TP并发量，并进行一次AP的21个语句查询
tiup bench ch --host 192.168.1.x  -Uhenley  -pxxxxxx -P3306 --warehouses 1 run -D tpcch -T 50 -t 1 --time 1m
```

### 测试摘要

```
tiup bench ch --host 192.168.1.x  -Uhenley  -pxxxxxx -P3306 --warehouses 1 run -D tpcch -T 50 -t 1 --time 1m

tpmC: 4168.9, tpmTotal: 9231.7, efficiency: 32417.2%
[Summary] Q1     - Count: 1, Sum(ms): 67.7, Avg(ms): 67.7
[Summary] Q10    - Count: 1, Sum(ms): 30.6, Avg(ms): 30.6
[Summary] Q11    - Count: 1, Sum(ms): 558.8, Avg(ms): 558.6
[Summary] Q12    - Count: 1, Sum(ms): 19.8, Avg(ms): 19.8
[Summary] Q13    - Count: 1, Sum(ms): 163.9, Avg(ms): 163.9
[Summary] Q14    - Count: 1, Sum(ms): 14.5, Avg(ms): 14.5
[Summary] Q15_ERR - Count: 1, Sum(ms): 277.5, Avg(ms): 277.5
[Summary] Q2     - Count: 1, Sum(ms): 1360.0, Avg(ms): 1359.5
[Summary] Q3     - Count: 1, Sum(ms): 90.3, Avg(ms): 90.3
[Summary] Q4     - Count: 1, Sum(ms): 116.4, Avg(ms): 116.4
[Summary] Q5     - Count: 1, Sum(ms): 204.9, Avg(ms): 204.8
[Summary] Q6     - Count: 1, Sum(ms): 18.9, Avg(ms): 18.9
[Summary] Q7     - Count: 1, Sum(ms): 21.2, Avg(ms): 21.3
[Summary] Q8     - Count: 1, Sum(ms): 195.2, Avg(ms): 195.1
[Summary] Q9     - Count: 1, Sum(ms): 265.0, Avg(ms): 265.0
QphH: 62.5

tiup bench ch --host 192.168.2.xx  -Uhenley  -pP@xxx -P4000 --warehouses 1 run -D tpcch -T 50 -t 1 --time 1m
tpmC: 1805.5, tpmTotal: 4092.0, efficiency: 14039.7%
[Summary] Q1     - Count: 1, Sum(ms): 145.6, Avg(ms): 145.6
[Summary] Q10    - Count: 1, Sum(ms): 275.2, Avg(ms): 275.1
[Summary] Q11    - Count: 1, Sum(ms): 330.5, Avg(ms): 330.4
[Summary] Q12    - Count: 1, Sum(ms): 124.3, Avg(ms): 124.4
[Summary] Q13    - Count: 1, Sum(ms): 98.4, Avg(ms): 98.4
[Summary] Q14    - Count: 1, Sum(ms): 275.1, Avg(ms): 275.1
[Summary] Q15_ERR - Count: 1, Sum(ms): 1.1, Avg(ms): 1.1
[Summary] Q2     - Count: 1, Sum(ms): 469.7, Avg(ms): 469.6
[Summary] Q3     - Count: 1, Sum(ms): 283.8, Avg(ms): 283.8
[Summary] Q4     - Count: 1, Sum(ms): 481.1, Avg(ms): 481.2
[Summary] Q5     - Count: 1, Sum(ms): 256.7, Avg(ms): 256.7
[Summary] Q6     - Count: 1, Sum(ms): 98.1, Avg(ms): 98.1
[Summary] Q7     - Count: 1, Sum(ms): 192.4, Avg(ms): 192.3
[Summary] Q8     - Count: 1, Sum(ms): 143.1, Avg(ms): 143.1
[Summary] Q9     - Count: 1, Sum(ms): 667.7, Avg(ms): 667.7
QphH: 62.4
```

### 测试总结

保留对 MySQL 8.0 和 TiDB 6.0 的内部参数不变， 单纯从单机 load data 数据插入、 tpmC 性能、以及 tpc-h 的性能数据表面来看，MySQL 8.0 要比 TiDB 6.0 要好。然而，实际情况并非如此，因为 TiDB 还有很大的调优空间。正如前面提到的，它们是两个不同的产品线，但这里证明了 TiDB 的友好性。它是十分兼容 MySQL 的，如果你从单机版的 TiDB 开始，随着业务的扩大，你可以自由、轻松地进行扩展。

我对 TiDB 的展望
-----------

软件开发的角度，TiDB 的解耦是完整的，如今 TiDB 已经发展到了 7.0 版本。我对 TiDB 未来的期待有三个方面：

- TiDB 模块源代码，可以做为分布式计算基础参考，派生更多的可能性，类似 presto 的路线延伸；
- TiKV 模块源代码，可以作为分布式存储参考，以后的发展方向可能是文件数据存储；
- PD 模块源代码的技术路径发展是轻量级的元数据存储的管理，三者兼进，TiDB 将能够最大化地帮助用户降低存储成本，提升计算弹性，通过分布式实现元数据最优存储，灵活、可靠，在更多场景得到应用。