对于超大文件也就是无法一次性加载到内存,行数据是 key:value,统计同一个,key 的不同 value 个数,并输出到文件,格式为 key:n,输出的文件假设也很大,也无法加载到内存中,求思路
1
zynlp 2018-06-11 10:46:02 +08:00 via iPhone
这种活就交给 python 吧
|
3
araraloren 2018-06-11 10:47:57 +08:00
思路不就是读多少处理多少么。。
|
4
huiyadanli 2018-06-11 10:48:14 +08:00
把超大文件处理到数据库中,然后用 sql 统计数据
|
5
wplct 2018-06-11 10:48:20 +08:00
java 不是可以按行读取么
|
6
wplct 2018-06-11 10:51:20 +08:00
要不,先跑一边计数每个 key 有多少个 value,然后一个个 key 分开处理,慢是慢些
|
7
xylophone21 2018-06-11 10:59:16 +08:00
超大是多大?目的是什么?(考试还是工程)
如果是工程问题,最简单的方法其实是转嫁矛盾,读一行,写一条数据到文件行不行?文件不好查找,直接用数据库行不行?数据库还不够,分表行不行?分表还不行,用跟牛 X 的数据库分表啊。 如果是考试,那就往 hadoop 生态,MapReduce 上扯。 |
8
MrXiong OP @xylophone21 直接上 MapReduce 进行处理?
|
9
EchoUtopia 2018-06-11 11:01:53 +08:00
postgres:
insert into words_count(word) values('example') on conflict do update count=words_count.count + 1 returning id |
10
wplct 2018-06-11 11:02:12 +08:00
all_key = {}
with open('f.text') as f: key = f.readline().split(':')[0] if key not in all_key: all_key[key] = 0 all_key[key] += 1 result = {} for key in all_key.keys(): values = set() with open('f.text') as f: key, value = f.readline().split(':') if key == key: values.add(value) result[key] = len(values) |
11
wplct 2018-06-11 11:02:48 +08:00
你可以再改成一次跑多个 key 的统计,
|
12
EchoUtopia 2018-06-11 11:02:57 +08:00
postgres:
insert into words_count(word) values('example') on conflict do update set count=words_count.count + 1 returning id |
13
FreeEx 2018-06-11 11:12:10 +08:00
流处理了解一下
|
14
kaiser1992 2018-06-11 11:14:17 +08:00
Java 读取文件哪有一次性加载到内存的
|
15
EchoUtopia 2018-06-11 11:15:58 +08:00
https://github.com/EchoUtopia/my-python-practices/blob/master/trie.js
之前用 js 统计了《心理学与生活》这本书的词频,用的前缀树,这本书纯文字只有 1M 多,我用 js 读取整本书、将单词插入前缀树、搜索一个单词、列出单词的频次并按照频次排序,所有操作加起来不到 0.5 秒。 |
16
BBCCBB 2018-06-11 11:24:20 +08:00
bufferreader 啊, 不都是流处理吗?
|
17
SoCrazyStone 2018-06-11 11:57:17 +08:00
Java 直接读就可以吧,不是一次加载进内存,然后存到数据库里,结束了再导到文件?
|
18
wplct 2018-06-11 12:35:56 +08:00
@EchoUtopia #15 想啥呢,内存放不下,应该是 gb 量级了
|
19
pathbox 2018-06-11 12:42:33 +08:00 via iPhone
一行一行的 read 处理 就没有大文件内存限制了
|
20
rrfeng 2018-06-11 12:44:17 +08:00
awk '!a[key:value]{n[key]++}END{for(i in n)print i,n[i]}'
|
21
rockyou12 2018-06-11 12:50:10 +08:00
lz 怕是从来没写过 java 的文件操作,如果直接用 stream 来读,本来就该用个小的 buffer 来读。不然直接用 nio 的 readline 就行了。自己谷歌下 java nio read file
|
22
CoderGeek 2018-06-11 12:55:49 +08:00
...一行一行就好了
|
23
EchoUtopia 2018-06-11 12:57:22 +08:00
@wplct #18 文件上 gb 量级不代表前缀树也有这么大。。
|
24
wplct 2018-06-11 12:59:48 +08:00
楼上的,楼主不是流式处理 ,是因为这个需求需要去重,一次性处理内存可能不够
|
25
panpanpan 2018-06-11 13:14:35 +08:00 via iPhone
导进数据库里面 group by 一下难道不是最简单的方式?
|
27
xmh51 2018-06-11 13:21:15 +08:00
分而治之 把大文件拆分掉成 N 份 每份都计算 key 的 value count 值(需要带上 value ),然后把 key 按 hashcode 计算得到文件里面。最后合并结果文件
|
28
xmh51 2018-06-11 13:21:57 +08:00
感觉像算法题 果然是算法题 ......
|
29
xmh51 2018-06-11 13:24:36 +08:00
优化下 分而治之 读大文件不用拆分,一行一行读即可,直接计算 hashcode,把 key value 直接放到 N 份文件中的指定一个文件中。然后直接计算结果,最后合并结果
|
31
verrickt 2018-06-11 13:29:31 +08:00 via Android 1
先对文件用外部排序按 key 排序。然后读一行,看下一行的 key,一样的话加计数,不一样把计数写到输出文件里。大体上还是外部排序+归并的思路
|
32
xmh51 2018-06-11 13:42:58 +08:00
@MrXiong 去重在 hash 之后的一个步骤。一共两次 第一次 归并 key value 到指定文档,第二次 去重计算 count
|
33
xmh51 2018-06-11 13:46:19 +08:00
@MrXiong 第一次 归并 key value 到指定的 n 个文件中(保证 key 相同的数据在同一个文件中,可以用 hashcode 分),第二次 去重计算 count,最好合并结果
|
34
20015jjw 2018-06-11 14:00:39 +08:00 via Android
data base 课最基本的内容吧
|
35
dangluren 2018-06-11 14:27:04 +08:00
你好,这种问题,就和 mapreduce 类似了。如果你不用 mapreduce,可以这样做(其实也是 mapreduce 的原理)
假如数据有 10G,你内存 1G, 假设比较均匀,不存在数据倾斜情况(倾斜不能太严重)。 1. 你先一行一行的读取,然后得到 key 的 hashcode, 然后对%20,得到的数是几,就写到第几个文件去。 2. 由第一步你就得到了 20 个文件了,如果数据没倾斜,大概一个就 500M, 这时候同一个 key 的肯定在同一个文件,进行处理就可以了。 3. 如果有点数据倾斜,就%30, %50 的尝试。如果某一个 key 就超过了 1G,某个 key 很大的情况下,你可以先把这个 key 过滤出来,写入到一个文件中,然后再使用布隆过滤器或者其他什么方法 |
36
kaiser1992 2018-06-11 15:11:48 +08:00
采用分治思想,借助 Hadoop
|
37
qingfengxm 2018-06-11 15:11:53 +08:00
不知道你说的超大文件有多大? 10G 还是 10T。你这说的其实就是大数据单词计数,mapreduce 或者 spark 搞定
|
38
dif 2018-06-14 19:14:13 +08:00
mapreduce
|