请问如何多线程批量抽取数据

【 TiDB 使用环境】测试/ Poc
【 TiDB 版本】7.5.0
【复现路径】做过哪些操作出现的问题
【遇到的问题:问题现象及影响】我希望读取TIDB中的一张表,数据量大概在500w左右,该表有一个唯一的自增id,我需要把它加载到我内存中。在oracle中我可以通过随机抽样simple(0.1)可以快速的获取这个自增id的数据分布,并且开多线程,每个线程通过 where id > xxx and id < xxx来限定取数范围,这样可以快速的加载数据。想了解下在tidb中是否有类似的操作或者其他方式来实现多线程并行读取的

1、通过开窗函数分组,分成不同的范围,参考:https://docs.pingcap.com/zh/tidb/stable/dev-guide-paginate-results#单字段主键表的分页批处理
2、可以参考下 TiDB 导出工具 dumpling 的逻辑,我理解 dumpling 导出时应该与你有同样的需求,项目地址:tidb/dumpling at master · pingcap/tidb · GitHub

第二种可能不太适用,第一种方式的话需要先通过max和min获取最大和最小的id,目前表数据量比较大,这个获取动作本身可能就需需要10-20秒,不像oracle那样不管数据量大小都是秒出的。

500W的表,对表主键ID使用窗口函数的话,还是比较快的,且这个只需要取值一次就可以了

这个结论怎么得出来的 :flushed:有理解有索引都会很快啊:thinking:

为啥不适用呢 :grinning:

第二种,因为有很多where条件,而且是偏动态的(前端业务触发的),所以没办法用导出导入工具来实现
第一种,表大概有5亿条数据,max min的数据范围差不多在1000w条,查询一次max需要1分钟左右的时间

感觉可以根据这个采样率,单独收集一下这个列的直方桶的统计信息。

就是不知道执行起来准确性和速度如何。

https://docs.pingcap.com/zh/tidb/stable/sql-statement-analyze-table

ANALYZE TABLE t COLUMNS c WITH 50 BUCKETS

比如给t表c列分50个桶收集一下统计信息

https://docs.pingcap.com/zh/tidb/stable/sql-statement-show-stats-buckets

然后

SHOW STATS_BUCKETS WHERE Table_name=‘t’ and Column_name=‘c’ ;

看一下这50个桶是怎么分界的,最大最小值是什么。

另外还需要考虑这个统计信息,查询的时候也会参考,不确定是否会对这个表的执行计划带来什么影响。
你可以自行考虑一下是否合适,以及这样收集的时间表现如何。

看你的需求比较像是shard bit rowid 功能吧

我有个更快的方式,用tikv scan直接读取,不过单线程读,读出来写可以多线程写,不过要写代码

1 个赞

通过rowid分片读

写个公用函数取ID范围,然后开多线程每次用函数取一部分,轮询往下循环。

请问如何通过rowid分片读,我看tidb里好像没有_rowid这个隐藏字段的

您的意思是用tikv client java去读tidb的数据库嘛?我搜了下貌似没看到有使用方法,请问有相关文档嘛?

tidb 有 tablesample 的语法,可以看一下

我试了下,的确可以,不过不太确定具体用法,文档里也没有详细说明,tablesample regions(),这个regions方法接收传参嘛?像oracle那样可以设置概率的

1 个赞

提供具体 SQL 与执行计划

不行,只能按 region,在每个 region 里面随机取一个数字

有文档的,看我发的文章里面就有

好像只能按照region来统计。

https://docs.pingcap.com/zh/tidb/stable/sql-statement-select#语法图

TableSampleOpt ::=
‘TABLESAMPLE’ ‘REGIONS’ ‘(’ ‘)’

语法图上就只有这个选项