单表近 7 亿条数据,现在要优化结构,进行去重,求个方案

2020-05-29 10:37:09 +08:00
 FONG2
以前设计是以请求编号为主键的,现在优化后以用户编号为主键,那么就存在大量重复数据了。
现在用 sql 查一下都得等半天,请问有啥好方法处理么
6367 次点击
所在节点    数据库
58 条回复
liuxu
2020-05-29 11:43:35 +08:00
@Lonersun 这个搞法岂不是得 7 亿个磁盘随机 io,要是是机械硬盘,一次 2-3 毫秒,假设 2 毫秒,700,000,000/86400/500=16 天。。

分析了一下,我建议这样:
1.新建个没有键的表(插入会更快)
2. 从原表通过主键一次性顺序读 1 万-10 万行
3.利用程序语言的 set 数据结构清洗数据
4.清晰后的数据拼接成一条或者几条 insert 插入新表
5.回到 2 循环执行到结束
6.在新表中给用户编号列创建唯一索引
enjoyCoding
2020-05-29 11:46:51 +08:00
建一张表 所有列组合不可重复 然后把这张表的数据插入到那张表里,忽略数据库报错可行么
FONG2
2020-05-29 11:53:32 +08:00
@liuxu
前 10w 条包含 好几个 张三 去重了
接下来 10w 条还有张三
那插到新表是不是还有重复?
xuanbg
2020-05-29 11:56:05 +08:00
重复数据不要了?
jones2000
2020-05-29 11:56:35 +08:00
直接把数据导入到 ES 里面, 通过 ES 来查吧, 慢就加节点机器。这点数据对 ES 来说不算什么。
liuxu
2020-05-29 12:20:37 +08:00
@FONG2 没想到这点,那这样

1.新建表 new_table,用户编号 user_id 为唯一索引
2. 从原表通过主键一次性顺序读 1 万-10 万行
3.利用程序语言的 set 数据结构清洗数据
4.清洗后的数据拼接成一条或者几条 insert 插入新表
先 select user_id from new_table where user_id not in (清洗后数据中的用户 user_id1,2,3,4...)
然后再 insert 批量插入

5.回到 2 循环执行到结束
6.在新表中给用户编号列创建唯一索引

那程序清洗时用 redis 的 set 数据结构缓存用户序列号,或者就用程序内部缓存,
看看 php 的 swoole,https://wiki.swoole.com/wiki/page/p-table.html,不过这种方案需要的内存很大
lscho
2020-05-29 12:53:27 +08:00
@liuxu 你这个第 4 条 not in 性能堪忧啊。。。既然都用上内存缓存了,直接把 userid 存内存不好吗。
makdon
2020-05-29 12:54:47 +08:00
感觉这个需求用 map reduce 还是很好做的
makdon
2020-05-29 12:55:55 +08:00
@makdon 建一个新库表,从旧表读所有数据,用 map reduce 去重,写去新表。需要考虑去重期间新写入的数据的临时存放。
liuxu
2020-05-29 13:02:08 +08:00
@lscho 我最下面不是说了么,也可以清洗程序放自己的内存缓存,就是内存消耗有点大
kethylar
2020-05-29 13:07:24 +08:00
单条数据大吗,不大全部弄出来放到文本文件也就几个 G 到几十个 G 而已,然后当作文本文件写脚本处理完之后再批量写到新表完事
nilai
2020-05-29 13:21:04 +08:00
迁移到 tidb 中
walkman660
2020-05-29 14:32:03 +08:00
7 亿条数据分成 N 份,找个性能好点得服务器并行处理每份数据去重
结果再每 2 份合并服务器上并行去重

理论上要比一次排序去重快
7 亿条数据一次处理资源上很容易遇到瓶颈
fs20
2020-05-29 15:00:04 +08:00
单表 7 亿,不愿意分表,单从 sql 查询效率角度而已,就没考虑过分区?
micolore
2020-05-29 15:06:33 +08:00
写代码分批取,然后再进行汇总,再进行去重应该不会很久。这是纯测试方案,没考虑线上一系列乱七八糟的因素。
CRDarwin
2020-05-29 15:13:02 +08:00
数据导出来,直接丢在 hive 里
wangyzj
2020-05-29 15:15:55 +08:00
首先考虑需求把
我觉得用户 id 作为主键还去重那不就是会扔掉不少数据?
这是为啥
hantsy
2020-05-29 15:19:41 +08:00
看使用场景了,一般比如银行,可能查自己半年内的记录吧。可以另外用一个数据库,保存完整数据。主数据库只保留近期数据。当然这个看需求是否满足,一般查询,仅使用主数据库查询快,历史记录数据针对用户想自定日期义查询。
goldenalex
2020-05-29 15:29:10 +08:00
去重
优化查询方法
优化数据结构

rm -rf /* 考虑一下?
woscaizi
2020-05-29 15:38:55 +08:00
把主键从请求编号变为用户编号;
这样同一个用户的多次请求怎么办?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/676577

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX