萌新求教大数据量联表写入

【 TiDB 使用环境】生产环境
【 TiDB 版本】5.4.0
【遇到的问题】
各位前辈好,新手诚心求助,我们公司目前正在寻找OLAP解决方案,现在调研tidb中,我们已经搭建了一个测试集群(5个节点,pd、db、监控共用一台,3个kv、1个flash),现在基础表已经导入完毕(数据量普遍几千万,最大的一个有14亿),现在我们想根据这些基础表,关联创建一个大宽表,用于之后开启FLASH来进行OLAP。
想请教下如何创建比较好呢?
我初步想法是先创建好表结构,再insert into xxx select … left join … left join …这样子,但不知道这样是不是会很慢,而且会不会超时。
想请教下是否有更好的办法?

【附件】

请提供各个组件的 version 信息,如 cdc/tikv,可通过执行 cdc version/tikv-server --version 获取。

1 个赞

用insert select很容易出现oom的情况,我建议你先用dumpling导出数据,dumpling支持使用sql语句进行导出。导出成sql文件或者csv都行,然后用lightning导入到指定的表中,导入之前,把导出的数据按照“库名.表名”的形式就行了

1 个赞

我理解的你的问题就是,现在要多表关联查询,再将查询结果导入本地一张大宽表。
我的方案是:
1/集群先扩容tiflush节点,每一台物理机一个tiflush节点
2/使用ALTER TABLE table_name SET TIFLASH REPLICA count为你的基础表新增tiflash副本 使用 TiFlash | PingCAP Docs
3/设置一下你的sql超时参数, 开发 Java 应用使用 TiDB 的最佳实践 | PingCAP Docs
4/使用你的insert into select 语句来制作你的大宽表

1 个赞

既然都是分布式系统了,那我们就简单点,直接分布式思路解决吧。

整体思路是分段+并发。

分段是根据查询进行大小表判断,然后小表按照主键范围扫描,每一段分配几千个值,在另一个表进行条件查询,查询结果在批量写入数据库。

每一段都是一个线程处理,多线程并发处理。并发度以及每一段的数量都可以进行参数化。

在配合容器化,直接可以飞起。

1 个赞

基础表在TIDB已经存在了,dumpling可以dump TIDB的表么?
我觉得把已经存在基础表专门dump出来再lightning进去有点怪 orz

1 个赞

insert into xxx select … left join … left join …
这个 很容易OOM,(主要受限事务大小,内存大小)需要调大事务大小,可以测试一下自己的集群能达到多数条一批。就可以估算出时间。

可以使用spring batch 批量读出再批写入。

感觉你好像没明白我的意思,你不是想insert into xxx select … left join … left join …吗,我的意思是,你可以把这个语句分开,分成insert和select ,insert部分用lightning代替,select部分用dumpling,这样操作会避免很多问题。
dump的写法:
./dumpling -u root -P 4000 -h 127.0.0.1 -o /tmp/test --filetype csv --sql ‘select … left join … left join …’ -F 100MiB --output-filename-template ‘test.sbtest1.{{.Index}}’

2 个赞

感觉你的好像很厉害,但是新人可能不太懂

这位大神说的是dumping导出命令,可以导sql查询的结果,详细请参考: 使用 Dumpling 导出数据 | PingCAP Docs

使用dumpling/lighting的方式可能比较好

谢谢前辈指导,我现在到公司,这就尝试一下。

1 个赞

谢谢前辈,我今天会试着用这种方式的,谢谢啦~

1 个赞

还是insert into select 但是带上条件,一部分一部分的导入看可不可以

这样肯定慢啊,你写个循环,分批提交呗。

祝你马到成功

集群已经挂了……正在扩容 T T

咋整的,是不是select消耗内存太多了,导致了tidb出现oom了

因为是测试环境,考虑到成本,所以我机器给的比较小,我把db、pd和监控都放在一个4核16g的节点上了。
然后我执行了一个select,节点负载瞬间特别高,接着机器就卡死了。

建议你先把select的sql优化一下,只要这个sql能正常执行就没问题了。不过看现在的样子,select消耗的内存太大了,导致机器直接无响应了,这种情况不是很好办,要么就优化sql,让sql不使用更多的内存,要么就扩大tidb节点内存,还有一个方式就是设置一下参数,让超过内存限制的事务落盘,这样可能就可以执行完sql了 TiDB 内存控制文档 | PingCAP Docs

你这个sql是一整个大事务,所有操作执行完才提交,释放内存,这样会占用大量内存,导致oom
目前给你提供两种解决方案:
1/假设表A join B,你可以将A表物理拆分为两个表A1,A2,这两个表合起来数据等于表A,用这两个表分别和B表join,将两次得出的结果和与A直接joinB的结果是一样的。
2/假设AjoinBjoinC,你可以先将AjoinB的结果算出来生成中间表,再拿这个中间表的结果去和c表join

总结:两种方案的本质都是将大事务拆分成多个小事务来执行