当前位置: 首页 > news >正文

【TiDB 插入性能优化实战:从 5 秒到毫秒级的跨越】

TiDB 插入性能优化实战:从 5 秒到毫秒级的跨越

背景与问题现象

前提条件

  • 数据库:TiDB(分布式关系型数据库)
  • 技术栈:JDK8 + MyBatis-Plus
  • 表结构:11 个字段,数据量约 200 万条

异常现象
线上环境发现某张表的 insert 操作异常缓慢,单次插入耗时高达 5 秒,远超业务预期(正常应在 100ms 以内)。从 TiDB 慢日志来看,所有慢 SQL 均为简单插入语句(如 insert into table (col1, col2...) values (...)),且无复杂逻辑或大字段。

排查过程:一步步定位根因

排查 1:排除连接池资源瓶颈

首先检查数据库连接池配置:最大连接数 max-active=100,通过监控发现同一秒内执行的 SQL 记录不足 80 条,远未达到连接池上限。因此,连接数不足并非问题原因

排查 2:聚焦 TiDB 事务执行链路

通过 TiDB 慢日志的“执行链路详情”发现,耗时几乎全部集中在 Prewrite 阶段(分布式事务两阶段提交的第一阶段)。

补充:Prewrite 阶段是 TiDB 分布式事务的核心环节,需向事务涉及的所有 TiKV Region 的 Leader 发送请求,写入数据、记录锁信息并验证冲突。该阶段耗时直接取决于涉及的 Region 数量和 TiKV 处理能力。

排查 3:发现 ID 生成策略的矛盾

检查表结构定义,发现主键字段明确配置了 AUTO_INCREMENT(自增主键),但查询数据库中已插入的 ID 时,却发现其毫无自增规律(数值为 16 位以上的大整数,且跳跃性极大)。

这是一个明显的异常点:表定义的自增策略与实际 ID 分布不匹配

排查 4:定位代码层的 ID 生成配置

查看项目代码的 MyBatis-Plus 全局配置,发现:

mybatis-plus:global-config:db-config:id-type: ASSIGN_ID  # 全局使用雪花算法生成 ID

同时,实体类 Entity 的主键字段 id 未单独指定 @TableId 注解(即未覆盖全局配置)。

结论:代码中全局启用了雪花算法生成 ID,覆盖了 TiDB 表的 AUTO_INCREMENT 配置,导致实际插入的 ID 为雪花 ID(跳跃性大),而非预期的连续自增 ID。

解决方案:统一 ID 生成策略

针对排查结果,通过代码调整统一 ID 生成策略:

  1. 实体类指定自增策略:在主键字段添加注解,覆盖全局雪花算法配置:

    public class TargetEntity {// 指定使用数据库自增策略,覆盖全局的 ASSIGN_ID@TableId(type = IdType.AUTO)  private Long id;// 其他字段...
    }
    
  2. 验证效果:重新部署后,新插入的数据 ID 按 1,2,3... 连续递增,符合 TiDB AUTO_INCREMENT 预期。慢日志显示 insert 耗时从 5 秒降至 50ms 以内,Prewrite 阶段耗时显著减少。

深度分析:五个关键问题解答

问 1:为什么雪花算法会导致插入变慢?

核心原因是 ID 分布分散导致 Region 数量激增

  • 雪花算法生成的 ID 由“时间戳+机器 ID+序列号”组成,看似递增但存在大范围跳跃(如多实例部署时,不同机器 ID 生成的 ID 差距极大)。
  • TiDB 按主键范围分裂 Region(默认 64MB/Region),跳跃的 ID 会让 200 万条数据散落在数百个小 Region 中。
  • Prewrite 阶段需要向每个涉及的 Region Leader 发送请求,Region 数量越多,总耗时越长(5 秒本质是数百个 Region 的交互延迟叠加)。

问 2:历史 200 万数据是否需要优化?如何优化?

是否需要优化:取决于历史数据的 Region 分布和操作性能:

  • 若历史数据的 Region 数量超过正常范围(200 万数据应集中在 2-3 个 Region),或涉及历史数据的查询/更新耗时高,则需要优化。

优化方法

  1. 无锁重组织 Region(推荐):
    通过 TiDB 的 REORGANIZE PARTITION 按历史 ID 范围合并分散的 Region:

    -- 按历史雪花 ID 的实际范围合并(替换为实际 ID 区间)
    ALTER TABLE your_table 
    REORGANIZE PARTITION 
    BETWEEN (1658555588888888888) AND (1658555588888988888) 
    INTO (PARTITION p_history VALUES LESS THAN (1658555588888988889));
    
  2. 重建表(适合非核心业务):
    低峰期通过临时表按 ID 排序重写数据,强制数据集中分布:

    CREATE TABLE temp_table LIKE your_table;
    INSERT INTO temp_table SELECT * FROM your_table ORDER BY id;  -- 按 ID 排序插入
    RENAME TABLE your_table TO old_table, temp_table TO your_table;
    

问 3:如何判断 Region 数量和分散程度?

1. 查看 Region 数量
  • TiDB Dashboard:登录 http://{tidb-ip}:2379/dashboard → “数据分布” → “表分布”,搜索目标表查看“Region 数量”。
  • SQL 查询
    SELECT COUNT(DISTINCT region_id) AS region_count
    FROM information_schema.tikv_region_status
    WHERE table_name = 'your_table';
    
    正常范围:数据量(MB)/64(默认 Region 大小),200 万数据(约 100MB)应在 2-3 个。
2. 判断 Region 是否分散
  • TiDB Dashboard:查看表的“Region 列表”,观察“范围起始(Start Key)”和“范围结束(End Key)”:

    • 连续分布:Region 范围依次衔接(如 [1,10000)[10000,20000))。
    • 分散分布:范围跳跃极大(如 [1658...888, 1658...900)[1658...950, 1658...999))。
  • SQL 验证:查询 Region 范围并检查连续性:

    SELECT region_id, hex(range_start) AS start_key, hex(range_end) AS end_key
    FROM information_schema.tikv_region_status
    WHERE table_name = 'your_table'
    ORDER BY range_start;
    

问 4:若沿用雪花算法,200 万数据会慢吗?

大概率会慢
雪花算法的 ID 跳跃性会导致 200 万数据分散在数百个 Region 中,引发:

  • 插入时 Prewrite 阶段需与大量 Region 交互,耗时随 Region 数量线性增加;
  • 查询/更新时需扫描多个分散 Region,Coprocessor 处理耗时飙升;
  • 大量小 Region 消耗 TiKV 内存和 PD 调度资源,间接降低集群性能。

仅在“单实例部署+ID 严格连续+无范围查询”的极端场景下,性能问题可能不明显,但分布式系统中几乎不满足。

问 5:雪花算法与主键自增的适用场景对比

维度雪花算法主键自增(如 TiDB AUTO_INCREMENT)
全局唯一性支持(跨库/跨服务)单库内唯一,TiDB 分布式自增支持全局唯一
ID 特征整体递增,可能跳跃严格连续(趋势)
数据分布可能分散(依赖 ID 生成规则)集中(按 ID 范围存储)
适用场景1. 跨库/跨服务全局唯一 ID 需求;
2. 不依赖数据库生成 ID;
3. 需要通过 ID 反推时间戳
1. 单集群内业务,无跨库唯一需求;
2. 频繁范围查询/排序;
3. 依赖 ID 连续性(如订单号);
4. 基于 TiDB 等分布式数据库优化性能

总结

本次案例的核心教训是:分布式数据库的 ID 生成策略需与存储特性匹配。TiDB 等分布式数据库依赖主键范围实现数据集中存储,雪花算法的 ID 跳跃性会破坏这一特性,导致性能问题。

实际开发中,应根据业务场景选择 ID 策略:需全局唯一时用雪花算法(但需优化 ID 分布),单集群内优先用数据库自增(尤其是 TiDB 的分布式自增),才能充分发挥分布式数据库的性能优势。

http://www.dtcms.com/a/573529.html

相关文章:

  • Kubernetes Recreate 部署策略完整实战指南
  • 企业级Agent智能体(智能小秘)之LangGraph智能体
  • 外卖开源系统源码设计思路:商家、骑手、用户三端一体化方案
  • MySQL数据库基础操作:
  • 有什么网站可以做商业网站需要多少钱
  • 早教网站模板哈尔滨门户网站制作哪家好
  • 从入门到精通:OpenAI Prompt Engineering 与 Prompt Caching 实战详解
  • HGDB单机修改IP地址或主机名(含Linux和windows )
  • 重庆公司章程网上查询平台网站建设优化话术
  • 神奇的工作室最新网站设计网站怎么设计
  • WordPress站点添加ssl证书东莞网站设计排行榜
  • Nestjs框架: 高可用微服务架构实践之动态gRPC客户端切换与异常处理优化
  • Git 拉取代码冲突操作
  • 【简易聊天室】使用 HTML、CSS、JavaScript 结合 WebSocket 技术实现
  • 外设模块学习(14)——雨滴传感器、土壤湿度传感器(STM32实现)
  • 小白银行测试初步了解(一)
  • 第14讲:HTTP网络请求 - Dio库的使用与封装
  • 西安市城乡建设管理局网站唐山专业网站建设公司
  • Flink集群部署以及作业提交模式详解
  • Windows系统Git的安装及在IDEA中的配置
  • Linux网络(二)——socket编程
  • 图书出版的幕后故事-《JMeter核心技术、性能测试与性能分析》背后不为人知的事
  • 最好的做网站公司有哪些河北网站推广优化
  • Voronoi 图及其在路径搜索中的应用
  • 网站模版自适应建设商务网站ppt
  • 舞台灯光透镜厂数字化:AI赋能光学检测与镀膜调控新范式
  • 买国外空间哪个网站好中国正式宣布出兵
  • 建设网站需要注册证书吗建站排行榜
  • AWS区域显示工具:统一化设计与实现
  • Valgrind 在嵌入式 Linux 平台:工作原理、典型场景与案例分析