1
liuxu 2020-05-29 10:46:19 +08:00
楼下,多列覆盖索引能救 7 亿吗
|
2
fixend 2020-05-29 10:54:12 +08:00
去重的规则是啥?随意选择一条?用 insert into `table2` select * from `table1` group by `id` 这样?
ID 必须是建一个非唯一索引,但估计也得跑很久很久很久 * N |
3
newtype0092 2020-05-29 10:54:46 +08:00
楼上分个表不是美滋滋?
|
4
fixend 2020-05-29 10:56:14 +08:00
|
5
reus 2020-05-29 10:57:36 +08:00 via Android
这还要问?除了加索引你还能干嘛?自己不会试验吗?要不你给个 ssh 让大家连上去给你优化优化?
|
6
Egfly 2020-05-29 10:59:17 +08:00
把原表 copy 一份,然后建个临时表,慢慢处理完,再替换原表?
|
7
dog82 2020-05-29 11:01:59 +08:00
写代码清洗插入新表,写 sql 估计不行
|
10
wysnylc 2020-05-29 11:10:39 +08:00
弄个大数据框架,慢慢洗
单靠数据库单表是做不到的 |
12
bugsnail 2020-05-29 11:13:56 +08:00
不要当这个表有 7 亿,你就当 7 百万数据,然后写个程序处理,写好之后,再把这个表分成 100 份就好,程序处理的结果放另外一张表里,这样估计是最好的处理方法了
|
13
Lonersun 2020-05-29 11:14:43 +08:00
1 、建立一张新表,用户编号为主键唯一索引;
2 、业务代码从老表读每一条数据,读到直接往新表插入,能插进去说明新表不存在,插不进去说明已存在,直接跳过 3 、跑完后用新表代替老表 如果不考虑数据实时更新的话这样是否可行? |
16
ysweics 2020-05-29 11:22:06 +08:00
1.上大数据清洗
2.好奇是什么数据,如果单表 7 亿数据,那么在单表 1 亿数据的时候就应该考虑后续方案了,盲猜是请求日志记录 |
19
Leanna 2020-05-29 11:34:26 +08:00
流水表还是要定期迁数据比较好
|
21
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.在新表中给用户编号列创建唯一索引 |
22
enjoyCoding 2020-05-29 11:46:51 +08:00
建一张表 所有列组合不可重复 然后把这张表的数据插入到那张表里,忽略数据库报错可行么
|
23
FONG2 OP |
24
xuanbg 2020-05-29 11:56:05 +08:00
重复数据不要了?
|
25
jones2000 2020-05-29 11:56:35 +08:00
直接把数据导入到 ES 里面, 通过 ES 来查吧, 慢就加节点机器。这点数据对 ES 来说不算什么。
|
26
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,不过这种方案需要的内存很大 |
27
lscho 2020-05-29 12:53:27 +08:00 via iPhone
@liuxu 你这个第 4 条 not in 性能堪忧啊。。。既然都用上内存缓存了,直接把 userid 存内存不好吗。
|
28
makdon 2020-05-29 12:54:47 +08:00
感觉这个需求用 map reduce 还是很好做的
|
29
makdon 2020-05-29 12:55:55 +08:00
@makdon 建一个新库表,从旧表读所有数据,用 map reduce 去重,写去新表。需要考虑去重期间新写入的数据的临时存放。
|
31
kethylar 2020-05-29 13:07:24 +08:00 via Android
单条数据大吗,不大全部弄出来放到文本文件也就几个 G 到几十个 G 而已,然后当作文本文件写脚本处理完之后再批量写到新表完事
|
32
nilai 2020-05-29 13:21:04 +08:00
迁移到 tidb 中
|
33
walkman660 2020-05-29 14:32:03 +08:00
7 亿条数据分成 N 份,找个性能好点得服务器并行处理每份数据去重
结果再每 2 份合并服务器上并行去重 理论上要比一次排序去重快 7 亿条数据一次处理资源上很容易遇到瓶颈 |
34
fs20 2020-05-29 15:00:04 +08:00
单表 7 亿,不愿意分表,单从 sql 查询效率角度而已,就没考虑过分区?
|
35
micolore 2020-05-29 15:06:33 +08:00
写代码分批取,然后再进行汇总,再进行去重应该不会很久。这是纯测试方案,没考虑线上一系列乱七八糟的因素。
|
36
CRDarwin 2020-05-29 15:13:02 +08:00
数据导出来,直接丢在 hive 里
|
37
wangyzj 2020-05-29 15:15:55 +08:00
首先考虑需求把
我觉得用户 id 作为主键还去重那不就是会扔掉不少数据? 这是为啥 |
38
hantsy 2020-05-29 15:19:41 +08:00
看使用场景了,一般比如银行,可能查自己半年内的记录吧。可以另外用一个数据库,保存完整数据。主数据库只保留近期数据。当然这个看需求是否满足,一般查询,仅使用主数据库查询快,历史记录数据针对用户想自定日期义查询。
|
39
goldenalex 2020-05-29 15:29:10 +08:00
去重
优化查询方法 优化数据结构 rm -rf /* 考虑一下? |
40
woscaizi 2020-05-29 15:38:55 +08:00
把主键从请求编号变为用户编号;
这样同一个用户的多次请求怎么办? |
41
zouqiang 2020-05-29 15:39:49 +08:00
实现一个 Bloom Filter
|
42
saulshao 2020-05-29 15:55:32 +08:00
首先建议要分表,不然你建立的这个新表仍然没法保证查询效率。并且如果考虑数据增长,最终你也没法处理这么巨大的数据量。
|
43
joesonw 2020-05-29 16:12:13 +08:00
建个新表, 弄个队列写个处理慢慢导呗. 插数据的时候也顺手丢队列.
|
44
william2ct 2020-05-29 17:34:56 +08:00
先不说怎么去重,我就问问,是不是国资企业
|
45
FONG2 OP @william2ct 答对了 但是没有奖励
|
47
stevenkang 2020-05-29 17:44:51 +08:00
建议用 SQL 跑吧,慢点就慢点,用程序跑更慢,亲身经历。
之前一台游戏日志数据库,单表 2 亿级别,用程序跑从晚上 2 点跑到早上 8 点多。 后面改成 SQL 将查询结果直接 insert 到另外一张表,一条 SQL 语句就搞定,时间缩短到 1-2 个小时就能跑完。 |
48
ConradG 2020-05-29 17:50:49 +08:00
标准手势是拆分后归并排序
|
49
nwg 2020-05-29 18:16:12 +08:00
定时任务 批量查询--判断重复--插入新分表
|
50
fashy 2020-05-29 18:35:42 +08:00
没太明白意思,是说优化后是根据用户编号去重么?一个用户编号只保存一条记录?
假设请求编号和用户编号都是 long 类型可以表示的话,(字符串的话 hash 可能会有冲突),用两个 bitmap 怎么样? 7 亿 /1024/1024/1024/8,一个 bitmap1g 左右内存就能放下了 第一个放每行记录的用户编号,重复的忽略,不重复的把该行记录的请求编号放到第二个 bitmap 对应的位置 最终第二个 bitmap 里面被标记的 index(原表里面的主键),就可以认为是去重后的数据记录了 然后批量读取这些 index 对应的数据,直接往新表里面插 最坏的情况,请求编号和用户编号都是唯一的,去重过程也就只需要 2G 左右的内存 |
51
myCupOfTea 2020-05-29 19:54:19 +08:00
hash 分区啊
|
52
myCupOfTea 2020-05-29 19:56:13 +08:00
我之前的项目是收集几千个网站数据的,按照网站编码 hash 分了 1000 个区,反正每次查询都需要带上网站编码,飞快
分区首先要有一个指标可以用来区分数据,其次每次查询必须带上它,那你就可以用分区呢 |
53
xupefei 2020-05-30 04:55:34 +08:00
bloom filter 过一遍,疑似重复的条目存下来用哈希表检查。
|
54
cs419 2020-05-30 06:39:25 +08:00
3 、5 台机器的集群
spark 或者 flink 跑一下 估计顶多一两个小时 就搞定了 |
55
nicebird 2020-05-30 10:10:19 +08:00
后台慢慢跑喽
|
56
pabno 2020-05-30 11:37:33 +08:00
不知道去重后的数据量有多少?
如果比较少的话,可以考虑创建一张新表,根据去重规则创建唯一索引,写给程序不断的从旧表 load 数据并插入到新表中,使用 ingore insert 。 如果数据比较多的话,依然可以使用这种方式,只不过要做多一层分表 |
57
laminux29 2020-05-30 13:52:07 +08:00
看了一下楼上的回答,把问题都限定在数据库产品与对应的操作方法上了。
其实大家应该跳出这个局限性。 题主的 7 亿条数据,本质是,一堆已经限定在特定硬件,特定算法所构建的环境里的数据结构了。 因此,按照数据结构与算法的基础处理方法,得先了解硬件特性,然后再来构造处理算法。而且还要考虑目前数据已经处在环境里的数据结构的特殊性。 在题主还没有交代物理设备与具体需求之前,我觉得大家不应该急着给出解决方案。 |
58
encro 2020-05-30 15:12:18 +08:00
题目没出清楚:
“以前设计是以请求编号为主键的,现在优化后以用户编号为主键,那么就存在大量重复数据了。” 主键能重复?还是你的主键意思是主要查询条件? 感觉以前类似你 7 亿订单,用订单 ID 查询即可,现在要建立一个用户表 5000 万用户数据,根据用户 ID 查询出用户信息,然后需要用用户 ID 去查用户所有订单。如果是这样可以根据用户 ID 建立分区表或者直接根据用户 ID 或者时间分表。 或者直接采用 es,想查几个月就几个月。 |