【问题标题】:design very large database for searching text设计用于搜索文本的非常大的数据库
【发布时间】:2012-02-13 11:07:30
【问题描述】:

我们需要设计一个系统,允许用户在大文本中按不同的关键词进行搜索,并且在未来,创建一些关于该关键词在一段时间内所有文章中出现的频率的基本报告。

我们将拥有:

  • 每天新增约 200,000 篇文章
  • 每篇文章文字约2KB
  • 文章保存 6 个月

为此,我们提出了以下解决方案:

  • 创建一个 SOLR 存储库来存储文章
  • 使用 MySQL 数据库存储文章附加信息

系统将通过关键字搜索SOLR,然后在MySQL中查找结果以检索更多信息。

那么,这是一个好方法吗?

如果大多数搜索只针对上个月添加的文章,那么保留两个数据库是否是个好主意,一个包含上个月添加的文章用于大多数搜索,另一个包含所有文章?

如果您有任何关于如何改进这一点的提示/技巧,我们将不胜感激。

提前致谢!

【问题讨论】:

标签: database database-design full-text-search


【解决方案1】:

我认为您的解决方案非常好。如果您想在常见查询上获得更快的响应,我会评估在 SOLR 之前放置一个 memcache 实例。

我不确定这两个数据库,您必须看看与随着时间的推移将记录从第一个数据库移动到第二个数据库的负担相比,性能优势是什么。我怀疑有很大的好处,但这只是直觉,不要相信我的话并进行实验。

另外,您是否考虑到如果您的数据集变得非常大,您可能需要一些水平可扩展的解决方案?

【讨论】:

  • 感谢您的快速回复。我将进行一些测试,看看移动记录或插入两者之间的区别。我考虑过数据库会变得非常大的事实,我认为我们可以使用 MySQL Cluster 来提高性能。您认为使用不同的数据库系统是否更合适,更适合水平扩展,例如 Cassandra?
  • 我会更担心文档本身而不是存储在 mysql 中的元数据,即使 200k 文档/天 * 2kB/doc = 400MB/天,也就是每年大约 144GB 的原始文本。 .. 实际上,这并不足以证明 Cassandra 的合理性,至少目前,恕我直言
【解决方案2】:

与其将数据同时存储在 MySQL 和 Solr 中,不如考虑现在试用 MySQL 5.6。您应该能够使用一个存储引擎来满足您的所有要求。

事实上,MySQL 多年来一直支持全文搜索,但只支持过时的MyISAM 表引擎。 MySQL 5.6 支持 InnoDB 表的该功能,这使其与 Ruby on Rails 等框架更加相关。

MySQL 全文搜索的文档位于:

http://dev.mysql.com/doc/refman/5.6/en/fulltext-search.html

查询语法可能对那些将其与 Solr 的功能进行比较的人特别感兴趣,位于:

http://dev.mysql.com/doc/refman/5.6/en/fulltext-boolean.html

【讨论】:

  • 感谢您的回答。我不知道 InnoDB 表上的 MySQL 全文搜索,但你认为它比 Solr 快吗?从您提供的第二个链接中,我没有找到任何有关 Solr 的信息。
  • 第二个链接没有提到 Solr,但显示了可能的查询类型。如果我在它和 Solr 之间做出决定,这只是我所期望的信息。
  • 我才刚刚开始针对 Solr 进行评估。我们只有数千份文档,而不是您在 6 个月的部署中拥有的数百万份文档。我将特别注意添加文档所需的时间,这是我们看到 Solr 最大的问题。
  • 好的,知道了。我们还必须考虑将文档添加到 SOLR 与插入数据库的性能影响。
【解决方案3】:

事实上,我对使用 Solr Search Platform 没有任何想法,但在我看来,您可以使用Java Content Repository JCR,这将让您以树格式获取数据库中的数据。因此,搜索将比平时快得多。 您必须查看此链接以获取有关它的更多信息

http://onjava.com/onjava/2006/10/04/what-is-java-content-repository.html

希望有帮助

【讨论】:

  • 我也会看看JCR 并做更多的研究。感谢提示
  • 我会小心最高级的,在这里。 “指数级更快”有一个非常明确的含义,所以你应该只在字面上正确的情况下做出这个声明——在这种情况下几乎肯定不是这样。
  • @Dathan 让我们说理论上就是这样。我正在使用eXo Platform 以及使用JCR 的Platform Gatein,我看到内容的读取速度非常快。 我想这就是 JCR 的目的。对于这种情况,我不确定是否对他有帮助。否则,他可以使用Apache Lucene
【解决方案4】:

您希望对每一列(Column1、Column2、Column3)进行索引查找,而不是对如此大的表进行表扫描。

问题是一个查询将使用一个索引。

如果您在 (Column1, Column2, Column3) 上创建一个索引,它仍然会为每个搜索执行一次表扫描,因为当使用索引时,即 Column1 它仍然必须检查 Column2 和 Column3 中的搜索关键字太同时,这些不是订购的。 - 索引仅针对 Column1 排序; Column2和Column2的顺序是随机的

所以你有 2 个解决方案:要么你改变表格布局,所以你没有 Column1、Column2 和 Column3,但只有 1 列带有搜索关键字:cname,如果你需要知道它是否是 Column1,2或 3 然后添加另一列,其整数表示 1,2 或 3。 在这个 cname 列上放置一个索引,你的搜索会很快。 但根据您拥有的其他列,这可能意味着您复制了一些数据。

这就是我会做的。如果这还不够,那么甚至拆分表,这样你就只有一个表(id,cname),并且使用 id 你可以从另一个表中查找你需要的其他列。如果表格变得太长,您甚至可以将其拆分,创建一个包含以 A 到 M 开头的单词的 cnameAM 和包含其余单词的 cnameNZ..

如果您无法更改表格布局: 而不是使用 1 个查询,而是使用多个查询

在每一列上放置一个索引并使用 3 个查询。 所以在 (id, Column1) 上建立索引,在 (id, Column2) 和 (id, Column3) 上建立索引 并做:

SELECT * FROM 'SearchTable' WHERE Column1='$SearchKeyword'
SELECT * FROM 'SearchTable' WHERE Column2='$SearchKeyword'
SELECT * FROM 'SearchTable' WHERE Column3='$SearchKeyword'

这 3 个选择会非常快,因为它们每个都会在其特定索引上进行查找 然后加入 3 个结果集以进行进一步处理或使用您检索到的 id 查找更多列

【讨论】:

    猜你喜欢
    • 2011-08-24
    • 2015-03-24
    • 2018-05-09
    • 2016-09-18
    • 1970-01-01
    • 2014-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多