处理大文件的技巧,如何提高性能

3
如果文件中有100万行数据,那么在没有进行逐行迭代的情况下(即顺序访问),我们不能直接跳到第50000行。这是我通过在谷歌上做了一些研究后得出的结论。
如果是这样,那么对于拥有1TB数据的数据库,它可以在几秒钟内搜索到一行,这是如何实现的呢?毕竟,在某种程度上数据库也是存储在格式化文件中,并带有元数据。
那么,有没有可能在1百万行记录的文件中实现如此快速的字符串搜索?哪种实现方法能够帮助我们处理如此大规模的数据......
注意:每行的长度可能会从10到100不等。
Java能否实现这个功能?

3
如果我有一个包含一百万行的文件,我不能直接跳到第50,000行而不是逐行迭代。这些信息是否已经排好序了?每一行是否都给出了该信息作为键值?如果是这样,可以使用更有效的算法通过排序后的键来查找该行。 - Andrew Thompson
2
“在一个拥有一百万行记录的文件中实现如此快速的字符串搜索是否可能?”我表示怀疑。数据库通常使用巧妙的算法,结合针对“非线性”访问进行优化的数据结构。 - Andrew Thompson
5个回答

8
你需要维护一份行的索引。我有一个库可以做到这一点,叫做Java Chronicle。一旦行被索引(当你写它们时它会构建索引),你可以在100 ns内随机访问这些行。
它被设计用于处理TB级别的数据,可以存储在同一个文件中或者相对较少的文件中。如果你有数千个文件,你需要使用不同的方法,因为每个文件的开销会变得显著。

2

1- 仅读取所有行一次
2- 将行号(作为键)和行的起始位置放入Map对象中。

然后,

您可以通过map.get(lineNumber)获取startingPostionOfLine。
找到startingPosition后,使用RandomAccessFile.seek(startingPosition)方法进行跳转。


1
记录一下,这个建议相当浪费:只需要一个long数组即可。这很可能比HashMap节省两个数量级的内存。 - Marko Topolnik

2
您可以为二分搜索调整文件结构。每行开头以唯一标记(一个字节序列,不在该行中使用)开始,后跟行号。搜索一行时,
  1. 跳到随机位置;
  2. 向前读取直到找到标记;
  3. 读取行号;
  4. 如果它是您要查找的行,则完成搜索;否则选择另一个随机位置跳转(根据找到的行号,要么大于当前位置,要么小于当前位置)。
您对行有的假设越多,跳跃就越少是随机的。例如,您可以从平均行长度估算位置。您还可以拥有一些行位置的缓存来改善猜测。

1

好的,如何使用RandomAccessFile跳转到第50000行? - Peter Lawrey
如果所有行的大小都相同,这会有什么问题吗? - Anton
3
这是一个很大的假设,但如果最大行长不太长的话,那就可以实现。 - Peter Lawrey
1
即使你要对文件建立索引,这也是几行代码的简单解决方案。然后你可以使用随机访问文件。无需使用第三方库。 - Anton
如果你想节省内存,可以存储每100行开头的位置。你可以跳过尽可能多的行,然后迭代剩下的部分。如果需要一般性索引,请使用像Lucene这样的工具来构建索引。 - Joshua Martell
显示剩余5条评论

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接