Skip to content

TiDB 性能优化最佳实践

SQL 优化

1. 索引优化

索引设计原则

  • 选择合适的索引类型:根据查询模式选择普通索引、唯一索引或联合索引
  • 避免过度索引:索引会增加写操作的开销,应只创建必要的索引
  • 考虑索引选择性:选择选择性高的列作为索引列
  • 联合索引顺序:将选择性高的列放在前面,范围查询列放在最后
  • 覆盖索引:尽量设计覆盖索引,减少回表查询

索引使用最佳实践

sql
-- 为频繁查询的列创建索引
CREATE INDEX idx_user_name ON users(name);

-- 创建联合索引,注意列的顺序
CREATE INDEX idx_user_name_age ON users(name, age);

-- 使用覆盖索引,避免回表查询
SELECT name, age FROM users WHERE name = 'test';

-- 避免在索引列上使用函数或表达式
-- 不推荐
SELECT * FROM users WHERE YEAR(create_time) = 2024;
-- 推荐
SELECT * FROM users WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';

-- 避免使用 LIKE 前缀通配符
-- 不推荐
SELECT * FROM users WHERE name LIKE '%test%';
-- 推荐
SELECT * FROM users WHERE name LIKE 'test%';

2. 查询优化

优化查询语句

sql
-- 只查询需要的列,避免 SELECT *
-- 不推荐
SELECT * FROM users;
-- 推荐
SELECT id, name, email FROM users;

-- 合理使用 LIMIT,避免返回大量数据
SELECT * FROM users LIMIT 100;

-- 避免在 WHERE 子句中使用 != 或 NOT IN,这会导致全表扫描
-- 不推荐
SELECT * FROM users WHERE status != 1;
-- 推荐(如果 status 有索引)
SELECT * FROM users WHERE status IN (2, 3, 4);

-- 优化 JOIN 查询,确保 ON 条件有索引
SELECT u.name, o.order_no FROM users u JOIN orders o ON u.id = o.user_id;
-- 确保 o.user_id 有索引

-- 合理使用子查询,避免嵌套过深
-- 不推荐
SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100);
-- 推荐
SELECT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;

使用执行计划分析

sql
-- 查看执行计划
EXPLAIN SELECT * FROM users WHERE name = 'test';

-- 查看详细执行计划
EXPLAIN ANALYZE SELECT * FROM users WHERE name = 'test';

-- 查看优化后的 SQL
EXPLAIN FORMAT=verbose SELECT * FROM users WHERE name = 'test';

3. 事务优化

优化事务设计

  • 减小事务范围:只在必要时使用事务,减少事务持有时间
  • 避免长事务:长事务会占用系统资源,影响并发性能
  • 合理设置隔离级别:根据业务需求选择合适的隔离级别,避免过度使用 Serializable
  • 使用批量操作:将多个小操作合并为一个批量操作,减少事务开销

事务优化示例

sql
-- 不推荐:多个小事务
BEGIN;
INSERT INTO orders(user_id, amount) VALUES(1, 100);
COMMIT;

BEGIN;
UPDATE users SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 推荐:合并为一个事务
BEGIN;
INSERT INTO orders(user_id, amount) VALUES(1, 100);
UPDATE users SET balance = balance - 100 WHERE id = 1;
COMMIT;

-- 使用批量插入
INSERT INTO users(name, email) VALUES
('user1', 'user1@example.com'),
('user2', 'user2@example.com'),
('user3', 'user3@example.com');

配置优化

1. TiDB 配置优化

关键配置参数

toml
# TiDB 配置文件示例
[server]
# 线程池大小,建议设置为 CPU 核心数
max-procs = 16

[performance]
# 启用 prepared plan cache
prepared-plan-cache-enabled = true
# 语句缓存大小
stmt-count-limit = 10000

[txn]
# 事务超时时间,根据业务需求调整
txn-total-size-limit = 10737418240  # 10GB
# 启用异步提交
enable-async-commit = true
# 启用 1PC
enable-1pc = true

[log]
# 日志级别,生产环境建议设置为 "error"
level = "error"

2. TiKV 配置优化

关键配置参数

toml
# TiKV 配置文件示例
[server]
# 线程池大小,建议根据 CPU 核心数调整
grpc-concurrency = 8

[raftstore]
# Raft 线程数,建议设置为 2
raft-base-tick-interval = "2s"
raft-election-timeout-ticks = 10

[rocksdb]
# 启用异步刷盘
enable-async-wal = true
# 启用自动压缩
max-background-compactions = 8
max-background-flushes = 4

[storage]
# 启用 HLC 时间戳分配
enable-ttl = true

3. PD 配置优化

关键配置参数

toml
# PD 配置文件示例
[schedule]
# 启用热点调度
hot-region-scheduler = true
# 启用 Region 均衡调度
balance-region-scheduler = true
# 启用副本均衡调度
balance-leader-scheduler = true
# 调度间隔
leader-schedule-limit = 4
region-schedule-limit = 20

架构优化

1. 集群拓扑优化

  • 合理规划节点数量:根据业务需求和数据量,合理规划 TiDB、TiKV 和 PD 节点数量
  • 组件分离部署:将 TiDB、TiKV、PD 和监控组件分离部署,避免资源竞争
  • 跨可用区部署:对于高可用性要求高的场景,采用跨可用区部署
  • 混合存储架构:结合 TiKV 和 TiFlash,优化 HTAP 场景性能

2. 数据分布优化

  • 合理设置 Region 大小:默认 96MB,可根据业务需求调整
  • 使用分区表:对于大表,使用分区表分散数据和热点
  • 数据分片:将数据按照业务规则分片,分布到不同的 TiKV 节点
  • 避免数据倾斜:设计合理的数据模型,避免数据集中在少数 Region

3. 读写分离

  • 使用 TiDB 只读节点:为只读查询分配专门的 TiDB 节点
  • 使用 TiFlash:将分析型查询路由到 TiFlash,减轻 TiKV 压力
  • 应用层读写分离:在应用层实现读写分离,将查询路由到合适的节点

热点处理

1. 热点问题识别

bash
# 使用 PD Control 查看热点 Region
tiup ctl pd -u http://<pd-host>:2379 hot read
tiup ctl pd -u http://<pd-host>:2379 hot write

# 查看热点 Region 详细信息
tiup ctl pd -u http://<pd-host>:2379 hot read <region-id>

2. 热点问题优化

数据模型优化

  • 使用打散列:在主键中添加随机后缀,分散数据分布
  • 使用范围分区:将大表按时间或其他维度分区,分散热点
  • 避免单调递增主键:使用 UUID、雪花 ID 等非单调主键,避免写入热点
sql
-- 不推荐:单调递增主键
CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_no VARCHAR(20),
    amount DECIMAL(10,2)
);

-- 推荐:使用雪花 ID 或 UUID
CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    order_no VARCHAR(20),
    amount DECIMAL(10,2)
);

-- 或使用分区表
CREATE TABLE orders (
    id INT AUTO_INCREMENT,
    order_no VARCHAR(20),
    amount DECIMAL(10,2),
    create_time DATETIME,
    PRIMARY KEY (id, create_time)
) PARTITION BY RANGE (YEAR(create_time)) (
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION p2025 VALUES LESS THAN MAXVALUE
);

调度策略优化

  • 调整 PD 调度参数:增加热点调度的频率和力度
  • 手动迁移热点 Region:对于持续的热点,可以手动迁移到负载较低的节点
  • 增加副本数:通过增加副本数,分散热点压力
bash
# 调整热点调度参数
tiup ctl pd -u http://<pd-host>:2379 config set schedule.hot-region-schedule-limit 8

# 手动迁移热点 Region
tiup ctl pd -u http://<pd-host>:2379 operator add transfer-leader <region-id> <store-id>

系统资源优化

1. CPU 优化

  • 合理分配 CPU 资源:根据组件特性,为不同组件分配合适的 CPU 资源
  • 关闭不必要的服务:关闭系统中不必要的服务,释放 CPU 资源
  • 优化线程池配置:根据 CPU 核心数,合理配置各组件的线程池大小
  • 使用高性能 CPU:选择高主频、多核的 CPU,提高处理能力

2. 内存优化

  • 合理配置内存参数:根据节点内存大小,合理配置各组件的内存参数
  • 优化 RocksDB 内存使用:调整 RocksDB 的 block cache 大小,避免 OOM
  • 启用内存限制:为各组件设置合理的内存限制,防止内存溢出
  • 使用大内存节点:对于 TiKV 和 TiFlash 节点,建议使用大内存配置

3. 存储优化

  • 使用高速存储:对于 TiKV 节点,推荐使用 NVMe SSD,提高 IO 性能
  • 合理配置 RAID:根据业务需求,选择合适的 RAID 级别
  • 优化文件系统:使用 XFS 或 EXT4 文件系统,优化文件系统参数
  • 定期清理日志:定期清理不必要的日志文件,释放磁盘空间

4. 网络优化

  • 使用高速网络:推荐使用万兆或更高速率的网络,减少网络延迟
  • 配置 Jumbo Frame:启用 MTU 9000,提高网络吞吐量
  • 优化网络参数:调整 TCP 缓冲区大小等网络参数,提高网络性能
  • 减少跨机房流量:将相关组件部署在同一机房,减少跨机房网络延迟

监控与调优

1. 关键监控指标

TiDB 监控指标

  • 查询延迟tidb_executor_statement_latency
  • QPS/TPStidb_server_qpstidb_server_tps
  • 连接数tidb_server_connections
  • 事务重试tidb_transaction_retry_total
  • 慢查询数tidb_slow_query_total

TiKV 监控指标

  • CPU 使用率tikv_server_cpu_seconds_total
  • 内存使用率tikv_server_memory_bytes
  • IOPStikv_engine_kv_write_bytes_totaltikv_engine_kv_read_bytes_total
  • Region 数量tikv_store_region_count
  • Raft 状态tikv_raft_is_leadertikv_raft_logs_bytes_total

PD 监控指标

  • 集群状态pd_cluster_status
  • Leader 状态pd_is_leader
  • 调度操作数pd_scheduler_operator_finish_total
  • 热点 Region 数pd_hot_region_count
  • 心跳延迟pd_heartbeat_timestamp_diff_seconds

2. 性能调优流程

  1. 建立性能基准:在优化前,建立系统的性能基准,包括 QPS、延迟、资源使用率等
  2. 监控和分析:通过监控系统,收集性能数据,分析性能瓶颈
  3. 确定优化目标:根据分析结果,确定具体的优化目标
  4. 实施优化措施:根据优化目标,实施相应的优化措施
  5. 验证优化效果:优化后,验证优化效果,与性能基准进行对比
  6. 调整和优化:根据验证结果,调整优化措施,持续优化

常见问题(FAQ)

Q1: 如何确定 TiDB 性能瓶颈?

A1: 可以通过以下步骤确定 TiDB 性能瓶颈:

  1. 查看监控面板,关注关键指标,如 CPU、内存、磁盘 IO、网络等
  2. 分析慢查询日志,找出执行时间长的 SQL
  3. 使用 EXPLAIN ANALYZE 查看 SQL 执行计划,确定优化点
  4. 查看 PD Control 热点信息,检查是否存在热点问题
  5. 综合分析以上信息,确定性能瓶颈

Q2: 如何优化 TiDB 写入性能?

A2: 优化 TiDB 写入性能的措施包括:

  1. 避免单调递增主键,使用 UUID 或雪花 ID
  2. 启用异步提交和 1PC
  3. 调整 TiKV 的 RocksDB 配置,优化写入性能
  4. 增加 TiKV 节点数量,分散写入压力
  5. 使用批量写入,减少事务开销

Q3: 如何优化 TiDB 查询性能?

A3: 优化 TiDB 查询性能的措施包括:

  1. 优化索引设计,创建合适的索引
  2. 优化 SQL 语句,避免全表扫描和复杂查询
  3. 使用覆盖索引,减少回表查询
  4. 合理使用 TiFlash,将分析型查询路由到 TiFlash
  5. 增加 TiDB 只读节点,分散查询压力

Q4: 如何处理 TiDB 热点问题?

A4: 处理 TiDB 热点问题的措施包括:

  1. 优化数据模型,避免单调递增主键
  2. 使用分区表,分散数据和热点
  3. 调整 PD 调度策略,增加热点调度频率
  4. 手动迁移热点 Region 到负载较低的节点
  5. 增加副本数,分散热点压力

Q5: 如何规划 TiDB 集群规模?

A5: 规划 TiDB 集群规模时,应考虑:

  1. 数据量和增长速度
  2. QPS/TPS 需求
  3. 高可用性要求
  4. 硬件资源限制
  5. 预算限制

建议从小规模集群开始,根据实际运行情况逐步扩展。可以参考 TiDB 官方提供的硬件配置建议,结合业务需求进行调整。