配置 TiDB 以优化性能




本文档介绍如何优化 TiDB 的性能,包括:

  • 常见工作负载的最佳实践。
  • 针对复杂性能场景的优化策略。

概述

要实现 TiDB 的最佳性能,需要仔细调整各项设置。在许多情况下,实现最佳性能需要将配置调整为非默认值。

默认的配置优先考虑稳定性而非性能。若需获得更高性能,你可能需要采用更激进的配置,甚至启用实验特性。本文推荐的配置基于生产环境部署经验和性能优化实践。

本文介绍了非默认的配置方式,包括其优势和潜在权衡。请根据你的工作负载需求,参考这些信息来优化 TiDB 设置。

常见负载的关键配置

以下配置常用于优化 TiDB 性能:

这些配置可以显著提升多种工作负载的性能。但与任何优化一样,在部署到生产环境之前,请务必在你的环境中进行全面测试。

系统变量

执行以下 SQL 语句以应用推荐的配置:

SET GLOBAL tidb_enable_instance_plan_cache=on; SET GLOBAL tidb_instance_plan_cache_max_size=2GiB; SET GLOBAL tidb_enable_non_prepared_plan_cache=on; SET GLOBAL tidb_ignore_prepared_cache_close_stmt=on; SET GLOBAL tidb_analyze_column_options='ALL'; SET GLOBAL tidb_stats_load_sync_wait=2000; SET GLOBAL tidb_opt_limit_push_down_threshold=10000; SET GLOBAL tidb_opt_derive_topn=on; SET GLOBAL tidb_runtime_filter_mode=LOCAL; SET GLOBAL tidb_opt_enable_mpp_shared_cte_execution=on; SET GLOBAL tidb_rc_read_check_ts=on; SET GLOBAL tidb_guarantee_linearizability=off; SET GLOBAL pd_enable_follower_handle_region=on; SET GLOBAL tidb_opt_fix_control = '44262:ON,44389:ON,44823:10000,44830:ON,44855:ON,52869:ON';

下表说明了部分系统变量配置的作用及注意事项:

系统变量说明注意事项
tidb_enable_instance_plan_cachetidb_instance_plan_cache_max_size启用实例级计划缓存而不是会话级缓存,在高并发连接或频繁使用 Prepare 语句的场景中,可以显著提升性能。实验特性,建议先在测试环境中验证,并随着执行计划缓存大小的增加监控内存使用情况。
tidb_enable_non_prepared_plan_cache启用非 Prepare 语句执行计划缓存,降低未使用 Prepare 语句应用的编译开销。
tidb_ignore_prepared_cache_close_stmt为每次执行后关闭执行计划的 Prepare 语句应用缓存执行计划。
tidb_analyze_column_options收集所有列的统计信息,避免因缺少列统计信息而导致执行计划不优。
tidb_stats_load_sync_wait将同步加载统计信息的超时时间从默认的 100ms 提高到 2s,确保 TiDB 在查询编译前加载所需的统计信息。增大此值会导致查询编译前的同步等待时间更长。
tidb_opt_limit_push_down_threshold提高将 LimitTopN 下推到 TiKV 的阈值。当存在多个索引选项时,调大该变量的值后,优化器更倾向于选择能优化 ORDER BYLimit 算子的索引。
tidb_opt_derive_topn启用从窗口函数中推导 TopNLimit仅支持 ROW_NUMBER() 窗口函数。
tidb_runtime_filter_mode启用本地模式的 Runtime Filter,提升 Hash Join 的执行效率。v7.2.0 引入,出于安全考虑默认关闭。
tidb_opt_enable_mpp_shared_cte_execution启用非递归公共表表达式 (CTE) 下推至 TiFlash。实验特性。
tidb_rc_read_check_tsREAD-COMMITTED 隔离级别下,启用此变量可避免获取全局时间戳的延迟和开销,从而优化事务级读延迟。此特性与可重复读 (REPEATABLE READ) 隔离级别不兼容。
tidb_guarantee_linearizability跳过从 PD server 获取提交时间戳的步骤,提升性能。该设置以牺牲线性一致性 (Linearizability)为代价,仅保证因果一致性,不适用于要求严格线性一致性的场景。
pd_enable_follower_handle_region启用 PD Follower 功能,允许 PD Follower 处理 Region 请求,从而将负载均匀分配至所有 PD server,降低 PD Leader 的 CPU 压力。
tidb_opt_fix_control启用高级查询优化策略,通过额外的优化规则和启发式策略提升性能。请在你的环境中进行充分测试,不同工作负载下的性能提升效果可能不同。

以下为 Optimizer Fix Controls 的详细说明,这些配置项可启用额外的优化能力:

  • 44262:ON:当分区表缺少全局统计信息时,使用动态裁剪模式访问分区表。
  • 44389:ON:对形如 c = 10 and (a = 'xx' or (a = 'kk' and b = 1)) 的过滤条件,尝试为 IndexRangeScan 更加完整地构造扫描范围,即 range
  • 44823:10000:为节省内存,计划缓存不会缓存参数数量超过该变量值的查询。将参数上限从默认的 200 提高到 10000,使带有超长 IN 列表的查询也能命中计划缓存。
  • 44830:ON:允许计划缓存缓存物理优化阶段生成的包含 PointGet 算子的执行计划。
  • 44855:ON:当 IndexJoin 算子的 Probe 端包含 Selection 算子时,优化器会选择 IndexJoin
  • 52869:ON:如果优化器能够为查询计划选择单索引扫描方法(非全表扫描),优化器会自动选择索引合并 index merge。

TiKV 配置

在 TiKV 配置文件中添加如下配置项:

[server] concurrent-send-snap-limit = 64 concurrent-recv-snap-limit = 64 snap-io-max-bytes-per-sec = "400MiB" [rocksdb] max-manifest-file-size = "256MiB" [rocksdb.titan] enabled = true [rocksdb.defaultcf.titan] min-blob-size = "1KB" blob-file-compression = "zstd" [storage] scheduler-pending-write-threshold = "512MiB" [storage.flow-control] l0-files-threshold = 50 soft-pending-compaction-bytes-limit = "512GiB" [rocksdb.writecf] level0-slowdown-writes-trigger = 20 soft-pending-compaction-bytes-limit = "192GiB" [rocksdb.defaultcf] level0-slowdown-writes-trigger = 20 soft-pending-compaction-bytes-limit = "192GiB" [rocksdb.lockcf] level0-slowdown-writes-trigger = 20 soft-pending-compaction-bytes-limit = "192GiB"

下表简要说明主要配置项及注意事项:

配置项说明注意事项
在 TiKV 扩缩容过程中,为并发快照传输和 I/O 带宽设置限制。提高这些限制可以加快数据迁移,从而缩短扩缩容所需的时间。需要在扩容速度与在线业务性能之间进行权衡。
rocksdb.max-manifest-file-size设置 RocksDB Manifest 文件的最大大小。Manifest 文件记录 SST 文件和数据库状态变更的元数据。增大该值可降低 Manifest 文件的写入频率,从而减少其对前台写入性能的影响。默认值为 128MiB。在存在大量 SST 文件(如数十万级别)的环境下,频繁的 Manifest 文件写入会影响写入性能。建议将该参数调高至 256MiB 或更大,以保持最佳性能。
启用 Titan 存储引擎,以降低写放大并缓解磁盘 I/O 瓶颈。该引擎尤其适用于 RocksDB 压缩无法跟上写入压力、待压缩字节持续积压的场景。仅当写放大成为主要瓶颈时建议启用。需要权衡以下因素:
  • 主键范围扫描可能受影响。
  • 空间放大会增加(极端情况下最高达到 2 倍)。
  • Blob 缓存会占用更多内存。
storage.scheduler-pending-write-threshold设置 TiKV 调度器写入队列的最大大小。当待写入任务的总大小超过该阈值时,TiKV 会拒绝新的写入请求并返回 Server Is Busy 错误。默认值为 100MiB。在高并发写入或短时写入突发场景下,适当提高该阈值(如 512MiB)有助于缓解压力。但若写入队列持续积压并反复超限,可能说明存在底层性能瓶颈,需进一步排查。
storage.flow-control.l0-files-threshold控制基于 kvDB L0 文件数量触发写入流控的阈值。提高该阈值可在高写入负载下减少写入阻塞。阈值过高时,若 L0 文件数量较多,可能导致更激进的压缩操作。
storage.flow-control.soft-pending-compaction-bytes-limit控制待压缩字节数的阈值,用于管理写入流控。超过阈值后会部分拒绝写入请求。默认软阈值为 192GiB。在写入密集型场景下,如果压缩进程跟不上,待压缩字节会持续积压,可能触发流控。适当调高该阈值可增加缓冲空间,但若积压持续存在,则说明底层存在性能瓶颈,需进一步排查。
需要手动将 level0-slowdown-writes-triggersoft-pending-compaction-bytes-limit 设置回默认值,以避免受流控参数影响。同时,建议将 RocksDB 相关参数设置为默认值,以保持压缩效率。详情参见 Issue 18708

请注意,上述表格中的压缩与流控参数调整,主要适用于以下规格的 TiKV 部署实例:

  • CPU:32 核
  • 内存:128 GiB
  • 存储:5 TiB EBS
  • 磁盘吞吐:1 GiB/s

写入密集型负载推荐调整

为优化 TiKV 在写入密集型负载下的性能与稳定性,建议根据实例的硬件规格,调整部分压缩与流控参数。例如:

这些设置有助于提升资源利用率,并减少写入高峰期的潜在瓶颈。

TiFlash-learner 配置

在 TiFlash-learner 配置文件中添加如下内容:

[server] snap-io-max-bytes-per-sec = "300MiB"
配置项说明注意事项
snap-io-max-bytes-per-sec控制从 TiKV 到 TiFlash 复制数据时允许使用的最大磁盘带宽。提高该值可加快初始数据加载和同步追赶的速度。占用过多带宽可能会影响在线业务性能,请在同步速度与系统稳定性之间进行合理权衡。

Benchmark

本节对比了默认配置(基线)与基于前文常见负载的关键配置优化后的性能表现。

在 1000 张表上运行的 Sysbench 负载

测试环境

测试环境如下:

  • 3 台 TiDB 服务器(16 核 CPU,64 GiB 内存)
  • 3 台 TiKV 服务器(16 核 CPU,64 GiB 内存)
  • TiDB 版本:v8.4.0
  • 测试负载:sysbench oltp_read_only

性能对比

下表对比了基线配置与优化配置下的吞吐量、延迟和执行计划缓存命中率。

指标基线配置优化配置提升幅度
QPS89,100100,128+12.38%
平均延迟(毫秒)35.8731.92-11.01%
P95 延迟(毫秒)58.9251.02-13.41%
执行计划缓存命中率 (%)56.89%87.51%+53.82%
计划缓存内存占用 (MiB)95.370.2-26.34%

主要优势

相比基线配置,实例级执行计划缓存 (Instance Plan Cache) 带来了显著的性能提升:

  • 更高的命中率:提升 53.82%(从 56.89% 增加到 87.51%)。

  • 更低的内存占用:降低 26.34%(从 95.3 MiB 降至 70.2 MiB)。

  • 更优的性能表现:

    • QPS 提升 12.38%。
    • 平均延迟降低 11.01%。
    • P95 延迟降低 13.41%。

工作原理

实例级执行计划缓存通过以下机制提升性能:

  • SELECT 语句的执行计划缓存在内存中。
  • 在同一 TiDB 实例的所有连接(最多 200 个)之间共享缓存的执行计划。
  • 可高效存储多达 1000 张表、5000 条 SELECT 语句的执行计划。
  • BEGINCOMMIT 语句会出现缓存未命中的情况。

实际应用收益

虽然基于简单 sysbench oltp_read_only 查询(每个执行计划约 14 KB)的基准测试仅显示了有限的提升,但在真实业务场景下,实例级执行计划缓存的收益会更显著:

  • 复杂查询的执行速度可提升至原来的 20 倍。
  • 相比会话级计划缓存,内存利用率更高。

实例级执行计划缓存特别适用于以下场景:

  • 有大量列的大表。
  • 复杂的 SQL 查询。
  • 高并发连接。
  • 多样化的查询模式。

内存效率

相比会话级计划缓存 (Session Plan Cache),实例级执行计划缓存 (Instance Plan Cache) 具有更高的内存利用率,原因如下:

  • 执行计划在所有连接间共享
  • 无需为每个会话重复存储执行计划
  • 更高的内存利用率和更高的命中率

在多连接和复杂查询场景下,若使用会话级计划缓存,为达到类似命中率需消耗更多内存,因此实例级计划缓存更高效。

Instance plan cache: Queries Using Plan Cache OPS

测试负载

执行以下 sysbench oltp_read_only prepare 命令加载数据:

sysbench oltp_read_only prepare --mysql-host={host} --mysql-port={port} --mysql-user=root --db-driver=mysql --mysql-db=test --threads=100 --time=900 --report-interval=10 --tables=1000 --table-size=10000

执行以下 sysbench oltp_read_only run 命令运行测试负载:

sysbench oltp_read_only run --mysql-host={host} --mysql-port={port} --mysql-user=root --db-driver=mysql --mysql-db=test --threads=200 --time=900 --report-interval=10 --tables=1000 --table-size=10000

更多信息,请参阅如何用 Sysbench 测试 TiDB

大记录值下的 YCSB 测试负载

测试环境

测试环境如下:

  • 3 台 TiDB 服务器(16 核 CPU,64 GiB 内存)
  • 3 台 TiKV 服务器(16 核 CPU,64 GiB 内存)
  • TiDB 版本:v8.4.0
  • 测试负载:go-ycsb workloada

性能对比

下表对比了基线配置与优化配置下的吞吐量(每秒操作数,OPS)。

指标基线配置 (OPS)优化配置 (OPS)提升幅度
Load data2858.55074.3+77.59%
Workloada2243.012804.3+470.86%

性能分析

从 v7.6.0 开始,Titan 默认启用。在 TiDB v8.4.0 中,Titan 的 min-blob-size 默认值为 32KiB。在此测试中,基线配置采用 31KiB 的记录大小,以确保数据主要存储在 RocksDB 中。而在关键配置中,将 min-blob-size 设置为 1KiB,使数据存储在 Titan 中。

关键配置下的性能提升,主要归因于 Titan 显著减少了 RocksDB 的压缩操作。如下图所示:

  • 基线配置:RocksDB 压缩总吞吐量超过 1 GiB/s,峰值超过 3 GiB/s。
  • 关键配置:RocksDB 压缩峰值吞吐量低于 100 MiB/s。

压缩开销的大幅降低有助于整体吞吐量的提升,这一提升体现在关键参数配置的优化效果中。

Titan RocksDB compaction

测试负载

执行以下 go-ycsb load 命令加载数据:

go-ycsb load mysql -P /ycsb/workloads/workloada -p {host} -p mysql.port={port} -p threadcount=100 -p recordcount=5000000 -p operationcount=5000000 -p workload=core -p requestdistribution=uniform -pfieldcount=31 -p fieldlength=1024

执行以下 go-ycsb run 命令运行测试负载:

go-ycsb run mysql -P /ycsb/workloads/workloada -p {host} -p mysql.port={port} -p mysql.db=test -p threadcount=100 -p recordcount=5000000 -p operationcount=5000000 -p workload=core -prequestdistribution=uniform -p fieldcount=31 -p fieldlength=1024

边缘场景与专项优化

本节介绍如何针对特定场景进行专项优化,帮助你在基础参数调优的基础上,根据实际业务需求对 TiDB 进行更有针对性的配置和调整。

识别边缘场景

执行以下步骤识别边缘场景:

  1. 分析查询模式和负载特征。
  2. 监控系统指标,定位性能瓶颈。
  3. 收集应用团队关于具体问题的反馈。

常见边缘场景

以下列举了一些常见的边缘场景:

  • 高频小查询导致 TSO 等待时间过高
  • 针对不同负载选择合适的最大 chunk 大小
  • 针对读密集型负载调优 coprocessor cache
  • 根据负载特性优化 chunk 大小
  • 针对不同负载优化事务模式和 DML 类型
  • 通过 TiKV 下推优化 GROUP BYDISTINCT 操作
  • 使用内存引擎缓解 MVCC 版本积压
  • 批量操作期间优化统计信息收集
  • 针对不同实例类型优化线程池设置

后续小节将分别介绍如何应对这些场景。针对每种情况,你需要调整不同参数或使用 TiDB 的特定功能。

高频小查询导致 TSO 等待时间过高

问题排查

如果你的业务负载包含大量高频小事务或频繁请求时间戳的查询,TSO (Timestamp Oracle) 可能成为性能瓶颈。你可以通过 Performance Overview > SQL Execute Time Overview 面板检查 TSO 等待时间是否在 SQL 执行时间中占据较大比例。如果 TSO 等待时间较高,可考虑以下优化措施:

方案 1:低精度 TSO

你可以通过启用低精度 TSO 功能 (tidb_low_resolution_tso) 来减少 TSO 等待时间。启用后,TiDB 会使用缓存的时间戳进行读取,从而降低 TSO 等待,但可能会读取到过时的数据。

此优化特别适用于以下场景:

  • 以读操作为主且对数据新鲜度要求不高的负载。
  • 对查询延迟要求高于绝对一致性的场景。
  • 应用可以容忍读取到几秒内历史数据的场景。

优势与权衡:

  • 通过启用使用缓存 TSO 的读取过时数据的功能,可以减少查询延迟,无需请求新的时间戳。
  • 在性能与数据一致性之间取得平衡:该功能仅适用于可接受读取过时数据的场景。不建议在需要严格数据一致性的场景中使用。

启用方法:

SET GLOBAL tidb_low_resolution_tso=ON;

方案 2:TSO 请求并行模式

tidb_tso_client_rpc_mode 系统变量用于切换 TiDB 向 PD 发送 TSO RPC 请求的模式。默认值为 DEFAULT。当满足以下条件时,可以考虑将该变量切换为 PARALLELPARALLEL-FAST,以获得潜在的性能提升:

  • TSO 等待时间在 SQL 查询总执行时间中占比较高。
  • PD 的 TSO 分配尚未成为瓶颈。
  • PD 和 TiDB 节点的 CPU 资源充足。
  • TiDB 与 PD 之间的网络延迟明显高于 PD 分配 TSO 的耗时(即 TSO RPC 的耗时主要由网络延迟决定)。
    • 你可以通过 Grafana TiDB 面板的 PD Client > PD TSO RPC Duration 查看 TSO RPC 请求耗时。
    • 你可以通过 Grafana PD 面板的 TiDB > PD server TSO handle duration 查看 PD 分配 TSO 的耗时。
  • TiDB 与 PD 之间因更多 TSO RPC 请求(PARALLEL 模式下为 2 倍,PARALLEL-FAST 模式下为 4 倍)带来的额外网络流量在可接受范围内。

切换并行模式的方法如下:

-- 使用 PARALLEL 模式 SET GLOBAL tidb_tso_client_rpc_mode=PARALLEL; -- 使用 PARALLEL-FAST 模式 SET GLOBAL tidb_tso_client_rpc_mode=PARALLEL-FAST;

针对读密集型负载调优下推计算结果缓存 (Coprocessor Cache)

通过优化下推计算结果缓存,可以提升读密集型负载下的查询性能。该缓存用于存储协处理器请求的结果,减少对热点数据的重复计算。优化建议如下:

  1. 通过下推计算结果缓存监控面板观察缓存命中率。
  2. 增大缓存容量,以提升大工作集下的命中率。
  3. 根据查询模式调整缓存准入阈值。

以下为读密集型负载的推荐配置:

[tikv-client.copr-cache] capacity-mb = 4096 admission-max-ranges = 5000 admission-max-result-mb = 10 admission-min-process-ms = 0

根据负载特性优化 chunk 大小

tidb_max_chunk_size 系统变量用于设置执行过程中每个 chunk 的最大行数。根据不同负载调整该值,可提升查询性能。

  • 对于高并发、小事务的 OLTP 负载:

    • 建议设置为 128~256(默认值为 1024)。

    • 可降低内存占用,提升 limit 查询的速度。

    • 适用场景:点查、小范围扫描。

      SET GLOBAL tidb_max_chunk_size = 128;
  • 对于复杂查询、大结果集的 OLAP 或分析型负载:

    • 建议将其值设置为 1024~4096

    • 扫描大量数据时可提升吞吐量。

    • 适用场景:聚合、大表扫描。

      SET GLOBAL tidb_max_chunk_size = 4096;

针对不同负载优化事务模式与 DML 类型

TiDB 提供多种事务模式和 DML 执行类型,你可以根据不同负载模式优化性能。

事务模式

你可以通过 tidb_txn_mode 系统变量设置事务模式。

  • 悲观事务模式(默认模式):

    • 适用于可能存在写冲突的一般负载。
    • 提供更强的一致性保障。
    SET SESSION tidb_txn_mode = "pessimistic";
  • 乐观事务模式

    • 适用于写冲突较少的负载。
    • 多语句事务下性能更优。
    • 示例:BEGIN; INSERT...; INSERT...; COMMIT;
    SET SESSION tidb_txn_mode = "optimistic";

DML 类型

你可以通过 tidb_dml_type 系统变量(自 v8.0.0 引入)控制 DML 语句的执行模式。

如需使用批量 DML 执行模式,将 tidb_dml_type 设置为 "bulk"。该模式适用于无冲突的大批量数据写入,可降低大规模写入时的内存消耗。使用前请确保:

SET SESSION tidb_dml_type = "bulk";

使用 TiKV 下推优化 GROUP BYDISTINCT 操作

TiDB 支持将聚合操作下推到 TiKV 层执行,以减少数据传输和处理开销。性能提升幅度取决于数据分布和查询特征。

适用场景

  • 理想场景(性能提升明显):

    • 分组列的基数较低(NDV 较小)。
    • 数据中存在大量重复值。
    • 典型示例:状态字段、类别编码、日期分组等。
  • 非理想场景(可能出现性能下降):

    • 分组列的基数很高(NDV 较大)。
    • 不重复的标识符或时间戳。
    • 典型示例:用户 ID、交易 ID 等。

配置方法

你可以在会话级或全局级别启用聚合下推优化:

-- 开启常规聚合下推 SET GLOBAL tidb_opt_agg_push_down = ON; -- 开启 distinct 聚合下推 SET GLOBAL tidb_opt_distinct_agg_push_down = ON;

使用内存引擎缓解 MVCC 版本积压

在高读写热点区域或垃圾回收、压缩不及时的情况下,过多的 MVCC 版本会导致性能瓶颈。自 v8.5.0 起,你可以通过启用 TiKV MVCC 内存引擎 (In-Memory Engine, IME) 来缓解该问题。只需在 TiKV 配置文件中添加如下内容:

[in-memory-engine] enable = true

在批量操作期间优化统计信息收集

通过管理统计信息的收集方式,可以在保持查询优化能力的同时提升批量操作的性能。本节介绍如何有效管理该过程。

何时关闭自动统计信息分析 (Auto Analyze)

在以下场景中,可以通过将系统变量 tidb_enable_auto_analyze 设置为 OFF 来关闭自动统计信息分析:

  • 进行大规模数据导入时。
  • 执行批量更新操作时。
  • 处理对时间敏感的批处理任务时。
  • 需要完全控制统计信息收集时机时。

最佳实践

  • 批量操作之前:

    -- 关闭自动 analyze SET GLOBAL tidb_enable_auto_analyze = OFF;
  • 批量操作之后:

    -- 手动收集统计信息 ANALYZE TABLE your_table; -- 重新开启自动 analyze SET GLOBAL tidb_enable_auto_analyze = ON;

为不同实例类型优化线程池设置

为提升 TiKV 的性能,应根据实例的 CPU 资源配置线程池。你可以参考以下原则进行优化:

  • 对于 8 至 16 核的实例,默认设置通常已经足够。

  • 对于 32 核及以上的实例,建议增大线程池大小,以更充分地利用资源。可按如下方式调整设置:

    [server] # 增大 gRPC 线程池 grpc-concurrency = 10 [raftstore] # 针对写密集型负载进行优化 apply-pool-size = 4 store-pool-size = 4 store-io-pool-size = 2

文档内容是否有帮助?