|
| 1 | +--- |
| 2 | +title: 如何用 Sysbench 测试 TiDB |
| 3 | +category: benchmark |
| 4 | +--- |
| 5 | + |
| 6 | +# 如何用 Sysbench 测试 TiDB |
| 7 | + |
| 8 | +本次测试使用的是 TiDB 3.0 Beta 和 Sysbench 1.0.14。建议使用 Sysbench 1.0 或之后的更新版本,可在 [Sysbench Release 1.0.14 页面](https://github.com/akopytov/sysbench/releases/tag/1.0.14)下载。 |
| 9 | + |
| 10 | +## 测试环境 |
| 11 | + |
| 12 | +- [硬件要求](/how-to/deploy/hardware-recommendations.md) |
| 13 | + |
| 14 | +- 参考 [TiDB 部署文档](/how-to/deploy/orchestrated/ansible.md)部署 TiDB 集群。在 3 台服务器的条件下,建议每台机器部署 1 个 TiDB,1 个 PD,和 1 个 TiKV 实例。关于磁盘,以 32 张表、每张表 10M 行数据为例,建议 TiKV 的数据目录所在的磁盘空间大于 512 GB。 |
| 15 | + 对于单个 TiDB 的并发连接数,建议控制在 500 以内,如需增加整个系统的并发压力,可以增加 TiDB 实例,具体增加的 TiDB 个数视测试压力而定。 |
| 16 | + |
| 17 | +IDC 机器: |
| 18 | + |
| 19 | +| 类别 | 名称 | |
| 20 | +|:---- |:---- | |
| 21 | +| OS | Linux (CentOS 7.3.1611) | |
| 22 | +| CPU | 40 vCPUs, Intel® Xeon® CPU E5-2630 v4 @ 2.20GHz | |
| 23 | +| RAM | 128GB | |
| 24 | +| DISK | Intel Optane SSD P4800X 375G * 1 | |
| 25 | +| NIC | 10Gb Ethernet | |
| 26 | + |
| 27 | +## 测试方案 |
| 28 | + |
| 29 | +### TiDB 版本信息 |
| 30 | + |
| 31 | +| 组件 | GitHash | |
| 32 | +|:---- |:---- | |
| 33 | +| TiDB | 7a240818d19ae96e4165af9ea35df92466f59ce6 | |
| 34 | +| TiKV | e26ceadcdfe94fb6ff83b5abb614ea3115394bcd | |
| 35 | +| PD | 5e81548c3c1a1adab056d977e7767307a39ecb70 | |
| 36 | + |
| 37 | +### 集群拓扑 |
| 38 | + |
| 39 | +| 机器 IP | 部署实例 | |
| 40 | +|:---- |:---- | |
| 41 | +| 172.16.30.31 | 3*sysbench | |
| 42 | +| 172.16.30.33 | 1\*tidb 1\*pd 1\*tikv | |
| 43 | +| 172.16.30.34 | 1\*tidb 1\*pd 1\*tikv | |
| 44 | +| 172.16.30.35 | 1\*tidb 1\*pd 1\*tikv | |
| 45 | + |
| 46 | +### TiDB 配置 |
| 47 | + |
| 48 | +升高日志级别,可以减少打印日志数量,对 TiDB 的性能有积极影响。开启 TiDB 配置中的 `prepared plan cache`,以减少优化执行计划的开销。具体在 TiDB 配置文件中加入: |
| 49 | + |
| 50 | +```toml |
| 51 | +[log] |
| 52 | +level = "error" |
| 53 | +[prepared-plan-cache] |
| 54 | +enabled = true |
| 55 | +``` |
| 56 | + |
| 57 | +### TiKV 配置 |
| 58 | + |
| 59 | +升高 TiKV 的日志级别同样有利于提高性能表现。 |
| 60 | + |
| 61 | +由于 TiKV 是以集群形式部署的,在 Raft 算法的作用下,能保证大多数节点已经写入数据。因此,除了对数据安全极端敏感的场景之外,raftstore 中的 `sync-log` 选项可以关闭。 |
| 62 | + |
| 63 | +TiKV 集群存在两个 Column Family(Default CF 和 Write CF),主要用于存储不同类型的数据。对于 Sysbench 测试,导入数据的 Column Family 在 TiDB 集群中的比例是固定的。这个比例是: |
| 64 | + |
| 65 | +Default CF : Write CF = 4 : 1 |
| 66 | + |
| 67 | +在 TiKV 中需要根据机器内存大小配置 RocksDB 的 block cache,以充分利用内存。以 40 GB 内存的虚拟机部署一个 TiKV 为例,其 block cache 建议配置如下: |
| 68 | + |
| 69 | +```toml |
| 70 | +log-level = "error" |
| 71 | +[raftstore] |
| 72 | +sync-log = false |
| 73 | +[rocksdb.defaultcf] |
| 74 | +block-cache-size = "24GB" |
| 75 | +[rocksdb.writecf] |
| 76 | +block-cache-size = "6GB" |
| 77 | +``` |
| 78 | + |
| 79 | +对于 3.0 及以后的版本,还可以使用共享 block cache 的方式进行设置: |
| 80 | + |
| 81 | +```toml |
| 82 | +log-level = "error" |
| 83 | +[raftstore] |
| 84 | +sync-log = false |
| 85 | +[storage.block-cache] |
| 86 | +capacity = "30GB" |
| 87 | +``` |
| 88 | + |
| 89 | +更详细的 TiKV 参数调优请参考 [TiKV 性能参数调优](/reference/performance/tune-tikv.md)。 |
| 90 | + |
| 91 | +## 测试过程 |
| 92 | + |
| 93 | +> **注意:** |
| 94 | +> |
| 95 | +> 此次测试并没有使用如 HAproxy 等负载均衡工具。在 TiDB 单一节点上进行 Sysbench 测试,并把结果相加。负载均衡工具和不同版本参数也会影响性能表现。 |
| 96 | +
|
| 97 | +### Sysbench 配置 |
| 98 | + |
| 99 | +以下为 Sysbench 配置文件样例: |
| 100 | + |
| 101 | +```txt |
| 102 | +mysql-host={TIDB_HOST} |
| 103 | +mysql-port=4000 |
| 104 | +mysql-user=root |
| 105 | +mysql-password=password |
| 106 | +mysql-db=sbtest |
| 107 | +time=600 |
| 108 | +threads={8, 16, 32, 64, 128, 256} |
| 109 | +report-interval=10 |
| 110 | +db-driver=mysql |
| 111 | +``` |
| 112 | + |
| 113 | +可根据实际需求调整其参数,其中 `TIDB_HOST` 为 TiDB server 的 IP 地址(配置文件中不能写多个地址),`threads` 为测试中的并发连接数,可在 “8, 16, 32, 64, 128, 256” 中调整,导入数据时,建议设置 threads = 8 或者 16。调整后,将该文件保存为名为 **config** 的文件。 |
| 114 | + |
| 115 | +**配置文件**参考示例如下: |
| 116 | + |
| 117 | +```txt |
| 118 | +mysql-host=172.16.30.33 |
| 119 | +mysql-port=4000 |
| 120 | +mysql-user=root |
| 121 | +mysql-password=password |
| 122 | +mysql-db=sbtest |
| 123 | +time=600 |
| 124 | +threads=16 |
| 125 | +report-interval=10 |
| 126 | +db-driver=mysql |
| 127 | +``` |
| 128 | + |
| 129 | +### 数据导入 |
| 130 | + |
| 131 | +在数据导入前,需要对 TiDB 进行简单设置。在 MySQL 客户端中执行如下命令: |
| 132 | + |
| 133 | +{{< copyable "sql" >}} |
| 134 | + |
| 135 | +```sql |
| 136 | +set global tidb_disable_txn_auto_retry = off; |
| 137 | +``` |
| 138 | + |
| 139 | +然后退出客户端。TiDB 使用乐观事务模型,当发现并发冲突时,会回滚事务。将 `tidb_disable_txn_auto_retry` 设置为 `off` 会开启事务冲突后的自动重试机制,可以尽可能避免事务冲突报错导致 Sysbench 程序退出的问题。 |
| 140 | + |
| 141 | +重新启动 MySQL 客户端执行以下 SQL 语句,创建数据库 `sbtest`: |
| 142 | + |
| 143 | +{{< copyable "sql" >}} |
| 144 | + |
| 145 | +```sql |
| 146 | +create database sbtest; |
| 147 | +``` |
| 148 | + |
| 149 | +调整 Sysbench 脚本创建索引的顺序。Sysbench 按照“建表->插入数据->创建索引”的顺序导入数据。该方式对于 TiDB 需要花费更多的导入时间。用户可以通过调整顺序来加速数据的导入。 |
| 150 | + |
| 151 | +假设用户使用的 [Sysbench](https://github.com/akopytov/sysbench/tree/1.0.14) 版本。我们可以通过以下两种方式来修改。 |
| 152 | + |
| 153 | +1. 直接下载为 TiDB 修改好的 [oltp_common.lua](https://raw.githubusercontent.com/pingcap/tidb-bench/master/sysbench/sysbench-patch/oltp_common.lua) 文件,覆盖 `/usr/share/sysbench/oltp_common.lua` 文件。 |
| 154 | +2. 将 `/usr/share/sysbench/oltp_common.lua` 的第 [235](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L235) 行到第 [240](https://github.com/akopytov/sysbench/blob/1.0.14/src/lua/oltp_common.lua#L240) 行移动到第 198 行以后。 |
| 155 | + |
| 156 | +> **注意:** |
| 157 | +> |
| 158 | +> 此操作为可选操作,仅节约了数据导入时间。 |
| 159 | +
|
| 160 | +命令行输入以下命令,开始导入数据,config 文件为上一步中配置的文件: |
| 161 | + |
| 162 | +{{< copyable "shell-regular" >}} |
| 163 | + |
| 164 | +```bash |
| 165 | +sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 prepare |
| 166 | +``` |
| 167 | + |
| 168 | +### 数据预热与统计信息收集 |
| 169 | + |
| 170 | +数据预热可将磁盘中的数据载入内存的 block cache 中,预热后的数据对系统整体的性能有较大的改善,建议在每次重启集群后进行一次数据预热。 |
| 171 | + |
| 172 | +Sysbench 1.0.14 没有提供数据预热的功能,因此需要手动进行数据预热。如果使用更新的 Sysbench 版本,可以使用自带的预热功能。 |
| 173 | + |
| 174 | +以 Sysbench 中某张表 sbtest7 为例,执行如下 SQL 语句 进行数据预热: |
| 175 | + |
| 176 | +{{< copyable "sql" >}} |
| 177 | + |
| 178 | +```sql |
| 179 | +SELECT COUNT(pad) FROM sbtest7 USE INDEX (k_7); |
| 180 | +``` |
| 181 | + |
| 182 | +统计信息收集有助于优化器选择更为准确的执行计划,可以通过 `analyze` 命令来收集表 sbtest 的统计信息,每个表都需要统计。 |
| 183 | + |
| 184 | +{{< copyable "sql" >}} |
| 185 | + |
| 186 | +```sql |
| 187 | +ANALYZE TABLE sbtest7; |
| 188 | +``` |
| 189 | + |
| 190 | +### Point select 测试命令 |
| 191 | + |
| 192 | +{{< copyable "shell-regular" >}} |
| 193 | + |
| 194 | +```bash |
| 195 | +sysbench --config-file=config oltp_point_select --tables=32 --table-size=10000000 run |
| 196 | +``` |
| 197 | + |
| 198 | +### Update index 测试命令 |
| 199 | + |
| 200 | +{{< copyable "shell-regular" >}} |
| 201 | + |
| 202 | +```bash |
| 203 | +sysbench --config-file=config oltp_update_index --tables=32 --table-size=10000000 run |
| 204 | +``` |
| 205 | + |
| 206 | +### Read-only 测试命令 |
| 207 | + |
| 208 | +{{< copyable "shell-regular" >}} |
| 209 | + |
| 210 | +```bash |
| 211 | +sysbench --config-file=config oltp_read_only --tables=32 --table-size=10000000 run |
| 212 | +``` |
| 213 | + |
| 214 | +## 测试结果 |
| 215 | + |
| 216 | +测试了数据 32 表,每表有 10M 数据。 |
| 217 | + |
| 218 | +对每个 tidb-server 进行了 Sysbench 测试,将结果相加,得出最终结果: |
| 219 | + |
| 220 | +### oltp_point_select |
| 221 | + |
| 222 | +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | |
| 223 | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | |
| 224 | +| point_select | 3\*8 | 67502.55 | 67502.55 | 0.36 | 0.42 | 141.92 | |
| 225 | +| point_select | 3\*16 | 120141.84 | 120141.84 | 0.40 | 0.52 | 20.99 | |
| 226 | +| point_select | 3\*32 | 170142.92 | 170142.92 | 0.58 | 0.99 | 28.08 | |
| 227 | +| point_select | 3\*64 | 195218.54 | 195218.54 | 0.98 | 2.14 | 21.82 | |
| 228 | +| point_select | 3\*128 | 208189.53 | 208189.53 | 1.84 | 4.33 | 31.02 | |
| 229 | + |
| 230 | + |
| 231 | + |
| 232 | +### oltp_update_index |
| 233 | + |
| 234 | +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | |
| 235 | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | |
| 236 | +| oltp_update_index | 3\*8 | 9668.98 | 9668.98 | 2.51 | 3.19 | 103.88| |
| 237 | +| oltp_update_index | 3\*16 | 12834.99 | 12834.99 | 3.79 | 5.47 | 176.90 | |
| 238 | +| oltp_update_index | 3\*32 | 15955.77 | 15955.77 | 6.07 | 9.39 | 4787.14 | |
| 239 | +| oltp_update_index | 3\*64 | 18697.17 | 18697.17 | 10.34 | 17.63 | 4539.04 | |
| 240 | +| oltp_update_index | 3\*128 | 20446.81 | 20446.81 | 18.98 | 40.37 | 5394.75 | |
| 241 | +| oltp_update_index | 3\*256 | 23563.03 | 23563.03 | 32.86 | 78.60 | 5530.69 | |
| 242 | + |
| 243 | + |
| 244 | + |
| 245 | +### oltp_read_only |
| 246 | + |
| 247 | +| 类型 | Thread | TPS | QPS | avg.latency(ms) | .95.latency(ms) | max.latency(ms) | |
| 248 | +|:---- |:---- |:---- |:---- |:----------------|:----------------- |:---- | |
| 249 | +| oltp_read_only | 3\*8 | 2411.00 | 38575.96 | 9.92 | 20.00 | 92.23 | |
| 250 | +| oltp_read_only | 3\*16 | 3873.53 | 61976.50 | 12.25 | 16.12 | 56.94 | |
| 251 | +| oltp_read_only | 3\*32 | 5066.88 | 81070.16 | 19.42 | 26.20 | 123.41 | |
| 252 | +| oltp_read_only | 3\*64 | 5466.36 | 87461.81 | 34.65 | 63.20 | 231.19 | |
| 253 | +| oltp_read_only | 3\*128 | 6684.16 | 106946.59 | 57.29 | 97.55 | 180.85 | |
| 254 | + |
| 255 | + |
| 256 | + |
| 257 | +## 常见问题 |
| 258 | + |
| 259 | +### 在高并发压力下,TiDB、TiKV 的配置都合理,为什么整体性能还是偏低? |
| 260 | + |
| 261 | +这种情况可能与使用了 proxy 有关。可以尝试直接对单个 TiDB 加压,将求和后的结果与使用 proxy 的情况进行对比。 |
| 262 | + |
| 263 | +以 HAproxy 为例。`nbproc` 参数可以增加其最大启动的进程数,较新版本的 HAproxy 还支持 `nbthread` 和 `cpu-map` 等。这些都可以减少对其性能的不利影响。 |
| 264 | + |
| 265 | +### 在高并发压力下,为什么 TiKV 的 CPU 利用率依然很低? |
| 266 | + |
| 267 | +TiKV 虽然整体 CPU 偏低,但部分模块的 CPU 可能已经达到了很高的利用率。 |
| 268 | + |
| 269 | +TiKV 的其他模块,如 storage readpool、coprocessor 和 gRPC 的最大并发度限制是可以通过 TiKV 的配置文件进行调整的。 |
| 270 | + |
| 271 | +通过 Grafana 的 TiKV Thread CPU 监控面板可以观察到其实际使用率。如出现多线程模块瓶颈,可以通过增加该模块并发度进行调整。 |
| 272 | + |
| 273 | +### 在高并发压力下,TiKV 也未达到 CPU 使用瓶颈,为什么 TiDB 的 CPU 利用率依然很低? |
| 274 | + |
| 275 | +在某些高端设备上,使用的是 NUMA 架构的 CPU,跨 CPU 访问远端内存将极大降低性能。TiDB 默认将使用服务器所有 CPU,goroutine 的调度不可避免地会出现跨 CPU 内存访问。 |
| 276 | + |
| 277 | +因此,建议在 NUMA 架构服务器上,部署 *n* 个 TiDB(*n* = NUMA CPU 的个数),同时将 TiDB 的 `max-procs` 变量的值设置为与 NUMA CPU 的核数相同。 |
0 commit comments