如何加速搜索大量文本文件(1TB)

18

我拥有一系列匿名的医疗数据文本文件(包括年龄、国家、症状、诊断等)。这些数据可以追溯至30年前,因此数据集相当大。总共有约20,000个文本文件,总计约1TB。

我需要定期搜索这些文件中特定字符串的出现情况(不是正则表达式)。有什么最快的方法可以搜索这些数据吗?

我已经尝试使用grep并递归地搜索目录,如下所示:

LC_ALL=C fgrep -r -i "searchTerm" /Folder/Containing/Files

上述方法唯一的问题在于搜索这些数据需要花费数小时(有时甚至半天!)。

有没有更快的搜索方式?目前我愿意尝试不同的方法,例如使用数据库、elasticsearch等。如果我选择使用数据库,将有约10亿条记录。

我的要求只有:

1)搜索将在我的本地计算机上进行(双核CPU和8GB RAM)

2)我将搜索字符串(而非正则表达式)。

3)我需要看到所有出现搜索字符串的位置以及所在文件。


1
解析数据并将其存储到数据库中。对数据进行索引。获利。 - Tony Stark
@Tony Stark - 文本文件中的数据格式基本正确,因此不确定是否需要解析。我可以编写一个脚本循环遍历目录并发送一个load data infile查询以快速上传文本文件。1)如果有一个1TB的表(再加上索引),这会成为问题吗?2)考虑到数据库仍然在我的本地硬盘驱动器上,搜索真的会更快吗?3)我需要返回文件名以知道数据属于哪个文件,如何在数据库中实现这一点? - M9A
今天的数据库系统来说,1TB并不算什么(你甚至可以将其加载到服务器内存中)。我不会在带有HDD的笔记本电脑上这样做,但这是你的选择,并且在专用硬件上使用SSD的性能会更好(读取速度更快)。在将数据放入数据库时,您始终可以创建带有数据源(文件名)的列。 - Tony Stark
@Tony Stark 很抱歉,我只能在本地机器上完成这个任务。我的问题是创建数据源列时存在大量的重复。例如,如果一个文件(1.txt)有50,000行,则数据库中将有50,000行,所有这些行都在数据源列中具有1.txt。这将极大地增加数据库的大小。 - M9A
2
你可以使用Elasticsearch单节点与Logstash。 - Jinna Balu
显示剩余8条评论
8个回答

5

已经有很多答案了,我只是想补充我的一些看法:

  1. 仅拥有 8GB 的内存,并使用 Lucene 或 Elasticsearch(内部使用 Lucene)或某些 grep 命令进行快速搜索,对于任何方法来说,持有如此庞大(1TB)数据将不足够好,原因很简单,所有这些系统都将数据保存在最快的内存中,以便能够更快地提供服务。而你只有 8GB(25% 应该留给操作系统,另外 25-50% 至少应用于其他应用程序),所以内存非常少。
  2. 升级 SSD、增加系统内存会有所帮助,但这相当繁琐,如果遇到性能问题,做系统垂直扩展也将是困难的。

建议

  1. 我知道你已经提到要在你的系统上执行此操作,但正如我所说,这不会产生任何实质性的好处,而且你可能会浪费很多时间和资源(基础架构和代码方面都有很多方法,正如各种答案中所述)。因此,我建议你按照我在另一个回答中提到的从上至下的方法来确定正确的容量。这将帮助你快速确定你选择的任何方法的正确容量。
  2. 在实现方面,我建议使用 Elasticsearch(ES),因为它非常容易设置和扩展,你甚至可以使用AWS Elasticsearch,它也是免费层级别中可用的,后续也可以快速扩展。虽然我不是 AWS ES 的铁粉,但如果你对 ES 很熟悉,它可以节省很多设置时间,让你能够快速开始。

  3. 为了使搜索更快,你可以将文件拆分成多个字段(标题、正文、标签、作者等),并仅索引重要字段,这将减少倒排索引大小,如果你只需要完全匹配字符串(而不是部分或全文搜索),那么你可以简单地使用 keyword 字段,这样处理更快速。

  4. 我可以继续谈论 Elasticsearch 的优点和如何进行优化,但这不是关键点,重点是任何搜索都需要大量的内存、CPU 和磁盘,其中任何一个出现瓶颈都会影响你的本地系统搜索和其他应用程序,因此建议你真正考虑在外部系统中执行此操作,而 Elasticsearch 确实是最适合分布式系统和最流行的开源搜索系统。

3
为了加快搜索速度,您需要一个倒排索引。为了能够添加新文档而无需重新索引所有现有文件,索引应该是增量的。
最早引入增量索引的开源项目之一是Apache Lucense。它仍然是最广泛使用的索引和搜索引擎,尽管现在其他扩展其功能的工具更受欢迎。Elasticsearch和Solr都基于Lucense。但只要您不需要Web前端、支持分析查询、过滤、分组、支持索引非文本文件或多主机集群设置的基础设施,Lucene仍然是最好的选择。 Apache Lucense是一个Java库,但它附带了一个完全功能的基于命令行的演示应用程序。这个基本演示应该已经提供了您所需的所有功能。
有一些Java知识的话,将应用程序适应到您的需求也很容易。您会惊讶于演示应用程序的源代码是多么简单。如果Java不是您的首选语言,其Python封装PyLucene也可能是一种选择。演示应用程序的索引已经几乎降至最低。默认情况下,不使用像词干提取或优化复杂查询等高级功能 - 这些功能在您的用例中可能不需要,但会增加索引的大小和索引时间。

Lucene的索引存储在文件系统中。索引的大小取决于您的数据,但是通过足够的冗余,它应该小于索引文档大小的30%。如果您有可能向系统添加快速SSD,则可以将索引移动到另一个驱动器并进一步加快查询速度。 - rmunge

3

正如几乎所有回答中提到的那样,您显然需要一个索引。您可以完全改进硬件,但既然您已经说它是固定的,我就不再详细解释了。

以下是一些相关的要点:

  1. 只为要查找搜索项的字段建立索引,而不是为整个数据集建立索引;
  2. 创建多级索引(即建立索引的索引),以使索引搜索更快。如果您的索引增长到超过8 GB,这将尤其相关;
  3. 我想推荐缓存您的搜索作为替代方案,但这会导致新的搜索再次需要半天时间。因此,预处理数据以构建索引显然比在查询时处理数据要好。

小更新:

这里有很多答案建议将数据放入云端。我强烈建议,即使是匿名的医疗数据,也要确认来源(除非您从网络上获取了数据)是否允许这样做。


1

这个话题有两个层面需要考虑:方法和具体软件使用。

方法: 根据你描述数据的方式,预索引会提供重要帮助。预索引将对数据进行一次扫描,并构建一个紧凑的索引,使得可以快速搜索并确定特定术语在存储库中出现的位置。

根据查询的不同,该索引将减少甚至完全消除对实际文档的搜索,即使是复杂的查询,如“查找所有出现AAA和BBB的文档”。

具体工具:

你所描述的硬件相对基础。运行复杂搜索将受益于大内存/多核硬件。有很好的解决方案 - elastic search、solr和类似的工具可以在强大的硬件支持下发挥魔力。

我认为你需要考虑两个选项,具体取决于你的技能和数据(如果OP可以共享数据样本)。 * 使用轻量级数据库(sqlite、postgresql)构建自己的索引,或者 * 使用轻量级搜索引擎。

对于第二种方法,使用describe hardware,我建议研究一下'glimpse'(以及支持的agrep实用程序)。Glimple提供了一种预索引数据的方式,使搜索非常快速。我在大型数据存储库上使用过它(几个GB,但从未达到TB)。
请参见:https://github.com/gvelez17/glimpse 显然,不像Elastic Search那样现代和功能丰富,但设置起来简单得多。它是无服务器的。 OP所描述的用例的主要好处是能够扫描现有文件,而无需将文档加载到额外的搜索引擎存储库中。

1

我为您提供3个选项。

  1. 您应该考虑升级您的硬件,将hdd升级为ssd可以将搜索速度乘以数倍。

  2. 立即提高搜索速度。 您可以参考这个问题中的各种建议。这种方法的主要思想是优化CPU负载,但您将受到HDD速度的限制。最大速度倍增器是您的核心数。

  3. 您可以对数据集进行索引。 因为您正在处理文本,所以需要一些全文搜索数据库。 Elasticsearch和Postgres是不错的选择。 此方法需要更多的磁盘空间(但通常少于x2的空间,具体取决于数据结构和要索引的字段列表)。 此方法将无限快速(几秒钟)。 如果您决定使用此方法,请仔细选择分析器配置,以匹配您的任务中被认为是单个单词的内容(Elasticsearch的这里是一个示例


1

如果数据结构格式一致,您是否考虑将所有数据导入到Elasticsearch中?

If yes, below are the quick steps:
1. Install filebeat on your local computer
2. Install elasticsearch and kibana as well.
3. Export the data by making filebeat send all the data to elasticsearch. 
4. Start searching it easily from Kibana.

0

Fs Crawler 可能会帮助您将数据索引到 Elasticsearch 中。之后,普通的 Elasticsearch 查询可以成为搜索引擎。


0

我认为,如果您缓存最近搜索的医疗数据,可能会有所帮助,而不是浏览整个1TB,您可以使用Redis/memcached。


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