Algorithm 快速遍历大型二进制文件的算法

Algorithm 快速遍历大型二进制文件的算法,algorithm,large-files,binary-search,Algorithm,Large Files,Binary Search,我有一个阅读大文件的问题需要解决,我对如何处理这个问题有一个大致的想法,但我想看看有没有更好的方法 问题如下:我有几个巨大的磁盘文件(64GB每个),每个文件都有2.5KB的记录(总共约25000000)。除其他字段外,每条记录都有一个时间戳,以及一个isValid标志,指示时间戳是否有效。当用户输入时间跨度时,我需要返回时间戳在指定范围内的所有记录 数据的布局是这样的,对于所有标记为“有效”的记录,时间戳单调增加。根本不应考虑无效记录。因此,文件通常是这样的(尽管范围要大得多): a[0]={

我有一个阅读大文件的问题需要解决,我对如何处理这个问题有一个大致的想法,但我想看看有没有更好的方法

问题如下:我有几个巨大的磁盘文件(
64GB
每个),每个文件都有
2.5KB
的记录(总共约
25000000
)。除其他字段外,每条记录都有一个时间戳,以及一个isValid标志,指示时间戳是否有效。当用户输入时间跨度时,我需要返回时间戳在指定范围内的所有记录

数据的布局是这样的,对于所有标记为“有效”的记录,时间戳单调增加。根本不应考虑无效记录。因此,文件通常是这样的(尽管范围要大得多):

a[0]={Time=11,IsValid=true};
[1]={Time=12,IsValid=true};
[2]={Time=13,IsValid=true};

[3]={Time=401,IsValid=false};// 在这种情况下,使用别人的数据库代码开始看起来是个好主意

无论如何,您需要摸索,直到找到有效数据的开头,然后读取,直到到达结尾

开始时,拍摄pot shots并相应地移动标记,与正常的二进制搜索相同 除非你点击了一条无效的记录,否则开始搜索一条有效的记录,只是从猜测中向前读就可以了


在文件上运行维护任务,用有效的时间戳替换无效的时间戳,或者维护外部索引,可能是值得的。

二进制搜索可能会带来一些随机性。实际上,随机算法对于大型数据集表现良好。

您可以使用修改的二进制搜索。其思想是进行常规的二进制搜索,找出下限和上限,然后返回有效的中间项

修改发生在当前条目无效的部分。在这种情况下,您必须找出两个端点,其中有一个有效条目。 e、 g如果中点为3

a[0]  = { Time=11, IsValid = true };
a[1]  = { Time=12, IsValid = true };
a[2]  = { Time=401, IsValid = false };
a[3]  = { Time=570, IsValid = false }; // <-- Mid point.
a[4]  = { Time=571, IsValid = false };
a[5]  = { Time=16, IsValid = true }; 
a[6]  = { Time=23, IsValid = true };
a[0]={Time=11,IsValid=true};
[1]={Time=12,IsValid=true};
a[2]={Time=401,IsValid=false};

[3]={Time=570,IsValid=false};// 听起来,改进的二进制搜索确实是一个很好的解决方案。如果无效记录的大块是一个问题,您可以通过跳过大小呈指数增长的块(例如1、2、4、8等)来处理它们,。。。。如果这使您超出了当前括号的末尾,请后退到括号的末尾,并以1,2,4,8…的步骤向后跳,。。。找到合理靠近中心的有效记录

您希望找到的无效记录块有多大?@Joni:应该不会超过一分钟(这是中间值),但我可以忍受某些边缘情况下的性能下降,只要平均速度快。+1谢谢。关于无效的时间戳,它们不能被“固定”,因为相关数据也是无效的(它与实时时钟完全不同步)。还有一件事:您如何确定无效区域的边界?通过线性扫描?
a[0]  = { Time=11, IsValid = true };
a[1]  = { Time=12, IsValid = true };
a[2]  = { Time=401, IsValid = false };
a[3]  = { Time=570, IsValid = false }; // <-- Mid point.
a[4]  = { Time=571, IsValid = false };
a[5]  = { Time=16, IsValid = true }; 
a[6]  = { Time=23, IsValid = true };