外观
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 = true3. 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/TPS:
tidb_server_qps、tidb_server_tps - 连接数:
tidb_server_connections - 事务重试:
tidb_transaction_retry_total - 慢查询数:
tidb_slow_query_total
TiKV 监控指标
- CPU 使用率:
tikv_server_cpu_seconds_total - 内存使用率:
tikv_server_memory_bytes - IOPS:
tikv_engine_kv_write_bytes_total、tikv_engine_kv_read_bytes_total - Region 数量:
tikv_store_region_count - Raft 状态:
tikv_raft_is_leader、tikv_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. 性能调优流程
- 建立性能基准:在优化前,建立系统的性能基准,包括 QPS、延迟、资源使用率等
- 监控和分析:通过监控系统,收集性能数据,分析性能瓶颈
- 确定优化目标:根据分析结果,确定具体的优化目标
- 实施优化措施:根据优化目标,实施相应的优化措施
- 验证优化效果:优化后,验证优化效果,与性能基准进行对比
- 调整和优化:根据验证结果,调整优化措施,持续优化
常见问题(FAQ)
Q1: 如何确定 TiDB 性能瓶颈?
A1: 可以通过以下步骤确定 TiDB 性能瓶颈:
- 查看监控面板,关注关键指标,如 CPU、内存、磁盘 IO、网络等
- 分析慢查询日志,找出执行时间长的 SQL
- 使用
EXPLAIN ANALYZE查看 SQL 执行计划,确定优化点 - 查看 PD Control 热点信息,检查是否存在热点问题
- 综合分析以上信息,确定性能瓶颈
Q2: 如何优化 TiDB 写入性能?
A2: 优化 TiDB 写入性能的措施包括:
- 避免单调递增主键,使用 UUID 或雪花 ID
- 启用异步提交和 1PC
- 调整 TiKV 的 RocksDB 配置,优化写入性能
- 增加 TiKV 节点数量,分散写入压力
- 使用批量写入,减少事务开销
Q3: 如何优化 TiDB 查询性能?
A3: 优化 TiDB 查询性能的措施包括:
- 优化索引设计,创建合适的索引
- 优化 SQL 语句,避免全表扫描和复杂查询
- 使用覆盖索引,减少回表查询
- 合理使用 TiFlash,将分析型查询路由到 TiFlash
- 增加 TiDB 只读节点,分散查询压力
Q4: 如何处理 TiDB 热点问题?
A4: 处理 TiDB 热点问题的措施包括:
- 优化数据模型,避免单调递增主键
- 使用分区表,分散数据和热点
- 调整 PD 调度策略,增加热点调度频率
- 手动迁移热点 Region 到负载较低的节点
- 增加副本数,分散热点压力
Q5: 如何规划 TiDB 集群规模?
A5: 规划 TiDB 集群规模时,应考虑:
- 数据量和增长速度
- QPS/TPS 需求
- 高可用性要求
- 硬件资源限制
- 预算限制
建议从小规模集群开始,根据实际运行情况逐步扩展。可以参考 TiDB 官方提供的硬件配置建议,结合业务需求进行调整。
