dumpling导出表内并发优化丨tidb工具分享

TiDB_PingCAP TiDB_PingCAP     2022-11-29     144

关键词:

李淳竹(lichunzhu),TiDB 研发工程师
SIG 组:Migrate SIG Community,主要涵盖 TiDB 数据处理工具,包含 TiDB 数据备份/导入导出,TiDB 数据变更捕获,其他数据库数据迁移至 TiDB 等

前言

Dumpling 是由 Go 语言编写的用于对数据库进行数据导出的工具。目前支持 MySQL 协议的数据库,并且针对 TiDB 的特性进行了优化。Go Dumpling! 让导出数据更稳定文章对 Dumpling 进阶使用进行了介绍。本文接下来将会介绍 Dumpling 内部表内并发的优化逻辑,从而帮助大家更深刻地理解 Dumpling 工作原理。

为什么需要表内并发

Dumpling 内部的导出逻辑可以用生产消费者模型进行诠释。生产者线程会遍历待导出数据库表集合,再会将生成好的导出 SQL 发送给消费者线程,由消费者线程将 SQL 执行结果格式化后写入文件。不难看出,不同消费者间可以互不干扰地进行并发导出。

由上文较容易推导的是,待导出的数据表彼此并无联系,可以由不同消费者并发导出。但大部分业务场景中,表和表之间的数据量差异巨大,很容易会出现线程空转在一张大表的情况。因此需要将大表划分为更小的“导出单元”(后文将简称为 chunk )以便于消费者线程并行导出,从而提升导出速度。chunk 划分也应该保证尽可能均匀,不均匀的 chunk 划分与大表小表并发导出的问题类似,会使得导出时间加倍,并极大提升数据库服务器内存使用

导出 MySQL 时的表内并发

那么如何将大表划分为更小且较为均匀的 chunk 呢?可以想到,相比于其他类型,整型数字可以较为均匀地划分为多个 limit 范围,是个最为理想的划分方式。同时,为了保证划分的整数范围能够命中索引,避免重复扫全表从而浪费计算资源,使用的划分范围应该为索引的第一列。由此可以得到针对 MySQL 的表内并发划分方式:

首先选取第一列为整数的索引列记为 field,按照主键、唯一索引、具有最大 Cardinality 的索引的顺序进行选取,从而保证该列整型数据尽量不同。选择好整数列后,Dumpling 通过 explain 语句粗略估算该表在限定条件下会导出的数据行数并记为 count。根据开头指定了划分行数大小的参数 rows,可以得到 Dumpling 需要将数据划分为 count/rows 个 chunk。随后通过 select min(field), max(field) 的方式得出在限定条件下的数据中的最大最小 field 记为 max_field 与 min_field。假设在这个范围内数据是呈现大体均匀分布的,则可以求出划分步长为 d=(max_field-min_field)*rows/count。各个表内并发 chunk 通过 where 条件约束,范围分别为 [min_field, min_field+d), [min_field+d, min_field+2d) …

从上述实现可以看出指定 rows 后划分 chunk 并不一定为 rows 行。同时,调大 rows 将直接增大各个 chunk 的步长范围即增大各个 chunk 的数据量。因此,如果发现 Dumpling 导出时对数据库内存消耗过大时,可以适当调小 rows 从而减小各个 chunk 的数据量。在实际导出场景中,rows 设置应较为适中:过大会消耗过多内存,且容易使并发效果不好;过小则容易导致 Dumpling 频繁向数据库请求少量数据,使导出速度下降。在目前的实践场景中,配置 --rows=200000 一般能够兼顾并发效果与导出速度。

导出 TiDB v3.0/v4.0 时的表内并发

从上文可以看出,当用户表不存在分布均匀的整数索引,或者 explain 语句获取数据行数的结果不准确时,表内并发效果将大打折扣。那么,TiDB 和 Dumpling 会怎么处理这一问题呢?在 TiDB 数据库如何计算一文中,提到了 TiDB 会为表中每行数据分配一个行 ID,用 RowID 表示。该 RowID 表内唯一且可以通过 select _tidb_rowid 的方式直接从数据库中获取。因此,简单的思路是直接将 _tidb_rowid 当作上文中的整型主键,采用相同的方式进行 chunk 划分即可。

然而,在 TiDB 高并发写入场景最佳实践中提到,为了避免 TiDB 写入热点,TiDB 表时常会使用 AUTO_RANDOM 列或在建表时加入 SHARD_ROW_ID_BITS 参数。这些参数会使得 _tidb_rowid 列分布极其不均匀,从而导致 Dumpling 导出表内并发划分 chunk 时划分不准确形成大 chunk,影响导出速度甚至引发 OOM。

TiDB 数据库的存储中,可以得到 TiDB 的数据映射为 KV 键值对后,以 range region 的形式存储在 TiKV 上,每个 region 保存了 [StartKey,EndKey) 范围的数据且 TiKV 会尽量保持每个 Region 中保存的数据不超过一定的大小。这些特性非常有利于 Dumpling 划分均匀的 chunk 数据。因此,Dumpling 通过 TiDB 的 INFORMATION_SCHEMA 库下的 TIKV_REGION_STATUS 表获取导出目标表所有 Region 的 StartKey,解码出所需要的 row_id,再使用得到 rowid 作为 WHERE 条件划分出 chunk。

从上述实现中可以看出 Dumpling 的表内并发的划分尺度为 region 大小,rows 的具体值已经不对划分结果产生影响。但是 rows 值设置与否仍将决定 Dumpling 是否采取表内并发的方式导出 TiDB 数据库。

导出 TiDB v5.0 时的表内并发

TiDB v5.0.0 开始支持了聚簇索引来避免 TiDB 此前使用 rowid 时的回表操作,提升写入查询速度。开启聚簇索引的表将不再有 _tidb_rowid 列。同时,在 split region 等特定场景下,region 的 StartKey 也不一定为合法值。但上文按 region 划分的思路仍然是行之有效的方法,然而需要更好的获取 region 边界划分数据的方法。

为了解决这一问题,TiDB 在 v5.0.0 及以上版本支持了 SELECT fields FROM table TABLESAMPLE REGIONS() 语法。执行该 SQL 后,TiKV 会扫描出表涉及到的每个 region 并获取第一个合法 kv 对,再将得到的数据返回给 Dumpling。例如使用该 SQL SELECT 聚簇索引的各个列时,该 SQL 会返回该表每个 REGION 中第一行聚簇索引的各列值用于均匀划分 chunk。

Dumpling 后续开发计划

以下为 Dumpling 后续开发的一些计划与设想。目前 Dumpling 已经迁移到 tidb repo,欢迎大家在 Dumpling Repo 一起交流讨论,参与开发。

一般来说,只要需要支持的数据库有对应的 database driver 或 client,比如 Oracle 数据库的 golang driver godror,都可以轻微改造导出语句和调用的 Go 代码库后就实现该数据库的导出支持。这里也欢迎社区的小伙伴们参与,帮助 Dumpling 支持导出更多类型的数据库。

Dumpling 目前不支持导出 TiDB Sequence,支持该功能将使导出功能更完整。

Dumpling 需要支持 checksum[4] [5] 校验来保证导出数据的正确性。

支持 Dumpling 使用 snapshot 模式导出 TiDB 时部分导出后从断点继续导出。

联 系:channel #sig-migrate in the tidbcommunity slack workspace, you can join this channel through this invitation link

使用dumpling从tidb/mysql导出数据

安装tiupinstalldumpling所需要权限shellSELECTRELOADLOCKTABLESREPLICATIONCLIENTPROCESS基本参数-h|--host:连接的数据库主机的地址,默认127.0.0.1-p|--password:连接的数 查看详情

tidb-使用br工具进行数据热备份与恢复(代码片段)

...本使用。在前面的章节中,我们介绍了dumpling将数据导出的方式,也可以作为一种备份的方式,并且导出的数据是极为可读的sql文件,并且也可以将数据导入Mysql中,但是在买对大数据量下快速的全量备份的场... 查看详情

dm分库分表ddl“悲观协调”模式介绍丨tidb工具分享

...过程中,这个复杂度转移到了数据迁移流程里。TiDBDM工具为用户提供了分库分表合并迁移功能,在数据迁移的过程中,支持将分表DML事件合并迁移,并一定程度支持上游分表进行DDL变更。本文以及后续文章主要介... 查看详情

tidb5.4发版丨新功能解读(代码片段)

...优化将使CPU占用率在现有基础上显著降低并间接帮助提升并发查询下的总体性能;最后,TiDB5.4在大规模数据同步场景下显著提升了同步工具Lightning的性能使得大规模的数据同步任务更轻松快捷。TiFlash存储层大幅优化行存... 查看详情

tidb6.0实战分享丨冷热存储分离解决方案(代码片段)

结论先行TiDB6.0正式提供了数据放置框架(PlacementRulesinSQL)功能,用户通过SQL配置数据在TiKV集群中的放置位置,可以对数据进行直接的管理,满足不同的业务场景需要。如:1.冷热分离存储,降低存储... 查看详情

备份的“算子下推”:br简介丨tidb工具分享(代码片段)

BR选择了在TransactionKV层面进行扫描来实现备份。这样,备份的核心便是分布在多个TiKV节点上的MVCCScan:简单,粗暴,但是有效,它生来就继承了TiKV的诸多优势:分布式、利于横向拓展、灵活(可以备份... 查看详情

dm分库分表ddl“乐观协调”模式介绍丨tidb工具分享(代码片段)

前言DM支持在线执行分库分表的DDL语句(通称ShardingDDL),先前的文章中,我们介绍了悲观模式,即当上游一个分表执行某一DDL后,这个分表的迁移会暂停,等待其他所有分表都执行了同样的DDL才在下游... 查看详情

tidb在ebay丨亿优百倍:商品数据服务缓存与代码优化

...些理解和研究。在上期的亿优百倍|商品数据服务TiDB性能优化(点击阅读)里,我们分享了对TiDB进行调优的方法,以提高了TiDB在eBay平台上使用的性能和稳定性。本期“亿优百倍”,我们分享了MIS中缓存层和代码层面的优化经验,... 查看详情

tidb6.5新特性解析丨过去一年,我们是如何让tiflash高效又稳定地榨干cpu?

...6.5版本。本文为系列文章的第一篇,介绍了TiFlash在高并发场景下的稳定性和资源利用率的优化原理。缘起最近的某天,我们测试TiFlash在高并发查询场景下的稳定性时,发现TiFlash终于可以长时间稳定将CPU完全打满࿰... 查看详情

坚如磐石:tidb基于时间点的恢复(pitr)特性优化之路丨6.5新特性解析

...TR技术的基本概念和工作原理,接着探讨了TiDB对PiTR的优化,包括PiTR的技术指标,稳定性和性能提升。最后,文章展望了TiDBPiTR未来的改进方向,将持续探索备份恢复的更多可能性。基于时间点恢复(PiTR... 查看详情

tispark原理之下推丨tidb工具分享(代码片段)

TiSpark是PingCAP为解决用户复杂OLAP需求而推出的产品。它通过Spark提供的拓展机制与内置的TiKVClientJava,在Spark之上直连TiKV进行读写,具有事务性读取、事务性写入与删除等能力。其中在事务性读取中基于SparkExtension实现了... 查看详情

hackathon实用指南丨快速给tidb新增一个功能(代码片段)

TiDBHackathon2022火热报名中!你报名了吗(还没报名看这里)?你有idea了吗(没有idea看这里)?有了idea,但是不够了解TiDB,不知道如何动手实践?本文将通过step-by-step的方式,介绍如何... 查看详情

技术分享丨不看后悔系列-java性能优化的7个方向!

...到了我们技术分享的时间啦今天给大家带来的是Java性能优化的7个方向,很有用的哦~本文转载自CSDN,版权归原创作者所有,如有侵权烦请告知,我们会立即删除表示歉意,谢谢!作者 查看详情

技术分享丨不看后悔系列-java性能优化的7个方向!

...到了我们技术分享的时间啦今天给大家带来的是Java性能优化的7个方向,很有用的哦~本文转载自CSDN,版权归原创作者所有,如有侵权烦请告知,我们会立即删除表示歉意,谢谢!作者 查看详情

tidb6.0:让tso更高效丨tidbbookrush(代码片段)

本文作者:h5n1,TiDB爱好者,目前就职于联通软件研究院,asktug主页1.前言TiDB作为一个分布式数据库,计算节点tidbserver和存储节点tikv/tiflashserver有着近乎线性的扩展能力,当资源不足时直接在线扩容即可。... 查看详情

数据技术前沿趋势tidb产品方向真实场景demo…丨pingcapdevcon2022产品技术论坛预览

...,有机会获得限定好礼哦!👆2022年5月,TiDB进入了V6时代。从TiDB第一个Beta版本开始,OLTPScale、Real-timeHTAP、TiDBCloud,我们一步步把理念变成现实。现在,数据库技术已进入Serveless的新时代,TiDB已经... 查看详情

tidb在微众银行核心批量场景的实践

...TiDB在贷款核心批量场景的应用,最后分享了基于TiDB优化方案的最佳实践和未来规划。TiDB的产品优势从2018年底微众银行开始接触TiDB的团队ÿ 查看详情

tidb笔记

...行垃圾回收(GC)将历史版本数据删除可水平扩展,增强并发处理能力TiKV存储数据(数据持久化),存储引擎集群,默认创建三副本(只有一个leader可以读写,其 查看详情