从1亿行字符串中搜索字符串

时间:2013-12-19 02:29:01

标签: database algorithm

我有这个文本文件包含一些md5哈希,其中有1亿行。我有另一个较小的文件,有几千md5哈希。我想从这个新的较小文件中找到这些md5哈希的相应索引到旧的较大文件。

最有效的方法是什么?可以在15分钟左右的时间内完成吗?

我尝试了很多东西,但它们不起作用。首先,我尝试将较大的数据导入数据库文件,并在md5哈希列上创建索引。创建此哈希需要永远。我甚至不确定这是否会提高查询速度。建议?

4 个答案:

答案 0 :(得分:3)

请勿在db中执行此操作 - 使用简单程序。

  1. 将小文件中的md5哈希读入内存中的哈希图,以便快速查找。
  2. 然后一次一行地读取大文件中的md5,并检查该行是否在哈希映射中。
  3. 哈希映射中的平均查找时间应该接近 O(1),所以这个的处理时间基本上有多快可以阅读大文件

    使用这种方法,今天的硬件很容易获得15分钟。

答案 1 :(得分:1)

首先:100Megarowsà32Bytes = ca. 3.2 GByte数据。在15分钟内读取它们可转换为每秒3.5兆字节,这对于现代硬件来说应该很容易实现。

我建议来使用数据库,但过程包含一些简单的步骤:

  1. 对数据进行排序 - 您只需执行一次此操作,并且可以对其中的大部分进行并行化
  2. 将小文件读入内存(分类为数组)
  3. 循环此阵列:
  4. 逐行读取大文件,与数组的当前行比较(首先比较第一个字节,然后是第一个和第二个,......),直到达到匹配(输出索引)或传递值(输出“未找到”)
  5. 转到下一个数组元素
  6. 初始排序可能需要超过15分钟,但查找应该非常快:如果你有足够的RAM(以及支持大于2GB的进程的操作系统),你应该能够获得至少一个比较率数量级更快!

答案 2 :(得分:0)

有专门设计用于在大文件中搜索多个字符串的算法。其中一个是Rabin-Karp。我有blog post about this

更简单地说,以下伪代码应该立即让你到那里:

Load your few thousand strings in a set data structure
For each line (index: i) in your file
    If that line appears in your set of values
        print i

这将非常快:设置的数据结构几乎是即时查找,因此IO将成为罪魁祸首,1亿个hashsums将在15分钟内完成,没有太多困难。

答案 3 :(得分:0)

假设:

(1)小文件中的每条记录都出现在大文件中

(2)每个文件中的数据是随机排序的。

选项:

(1)对于大文件中的每个记录,线性搜索小文件以进行匹配。由于大多数搜索都找不到匹配项,因此时间将接近  Nlarge * Nsmall * k 其中k表示尝试一场比赛的时间。

(2)对于小文件中的每个记录,线性搜索大文件以查找匹配项。由于每次搜索都会找到一个匹配项,因此时间会很长  Nlarge / 2 * Nsmall * k。

这看起来比选项(1)快两倍 - 但前提是你可以将大文件完全放入快速内存中。您可能需要6 GB的RAM。

(3)将小文件分类为易于搜索的形式。平衡的二叉树是最好的,但排序的数组几乎一样好。或者你可以相信一些方便的哈希表对象的作者在CS学校受到关注。对于大文件中的每个记录,搜索结构化小文件以查找匹配项。时间会是  log2 Nsmall * s 对小文件进行排序,其中s表示对一条记录进行排序的时间,加上  log2 Nsmall * Nlarge * k 用于扫描。这给出了总时间  log2 Nsmall *(s + Nlarge * k)。

(4)将大文件排序为易于搜索的形式。对于小文件中的每个记录,搜索结构化大文件以查找匹配项。时间会是  log2 Nlarge * s 排序大文件加  log2 Nlarge * Nsmall * k 对于扫描,总共给出了  log2 Nlarge *(s + Nsmall * k)。

选项(4)显然是最快的,因为减少任何系数的Nlarge支配所有其他改进。但是,如果从大文件派生的可排序结构不能完全适合RAM,那么选项(3)可能会变得更快。

(5)将大文件分类为易于搜索的形式。将此结构分解为适合您的RAM的部分。对于每个这样的片段,将片段加载到RAM中,然后对于小文件中的每个记录,搜索当前加载的片段以进行匹配。时间会是  log2 Nlarge * s 排序大文件加  log2 Nlarge * Nsmall * k * p 对于扫描,结构被分成p个部分,总共给出了  log2 Nlarge *(s + Nsmall * k * p)。

使用您为Nlarge和Nsmall指示的值,以及足够的RAM以便p可以保持为单个数字,选项(5)似乎可能是最快的。