【问题标题】:How to improve performance of mongo simple search query如何提高 mongo 简单搜索查询的性能
【发布时间】:2014-02-27 20:01:19
【问题描述】:

这是对 mongodb 中的简单搜索的解释,它需要超过 2.4 秒或更长时间来检索数据。如果我添加索引(搜索参数)则需要超过 5 秒。

查询

    db.CX_EMPLOYEES.find({ "$or" : [{ "AML_FULLNAME" : /RAJ/ }, 
{ "AML_FULLALIAS" : /RAJ/ }] })

解释

 {
        "cursor" : "BasicCursor",
        "isMultiKey" : false,
        "n" : 79,
        "nscannedObjects" : 504570,
        "nscanned" : 504570,
        "nscannedObjectsAllPlans" : 504570,
        "nscannedAllPlans" : 504570,
        "scanAndOrder" : false,
        "indexOnly" : false,
        "nYields" : 0,
        "nChunkSkips" : 0,
        "millis" : 2423,
        "indexBounds" : {},
        "server" : "SERVER:27017"
    }

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    为 2.6 版本的 MongoDb 计划的是 full text search 功能。如果启用,它可以作为当前版本中的开发预览版使用。

    鉴于您的查询的性质,它可能是仅使用 MongoDb 可能有效的唯一选项。当您尝试根据您提供的正则表达式进行“字符串包含”搜索时,考虑到您的集合的大小,执行搜索以匹配多个字段上的字符串的性能将非常糟糕。虽然它在概念上是一个简单的查询,但翻译成一个有效的查询是非常困难的。 Mongo 需要扫描每个文档以查找匹配项。将单词分开并没有帮助,因为 Mongo 仍然需要扫描每个文档。

    如果您可以锚定正则表达式,这意味着它将更改为“字符串开头”而不是“字符串包含”,如果您对字符串进行规范化以忽略所有字符大小写,则性能应该是合理的,并意识到匹配仍然是准确的。例如,a 不是 á,需要进行特殊处理。

    Mongo 对此类查询的支持确实仅限于生产使用。您可能会发现全文搜索功能也不适合。如果此查询很重要,我建议考虑替代搜索机制。例如,可能会查看Elastic Search 之类的内容。

    【讨论】:

    • 在 mongodb 中使用全文搜索功能是一种可靠的方法或解决方案吗..?我发现不建议在生产中使用它。
    • 2.6 目前处于候选版本中。我建议您可能要考虑非 Mongo 解决方案。
    【解决方案2】:

    没有任何理由在此搜索参数上添加索引,因为您使用的是 regExp。仅当 regExp 开头有一个锚时,索引才能使用 regExp 改进查找。

    db.CX_EMPLOYEES.find({ "$or" : [{ "AML_FULLNAME" : /^RAJ/ }, { "AML_FULLALIAS" : /^RAJ/ }] })
    

    来自documentation

    $regex 只有在正则表达式在字符串的开头(即 ^)有一个锚点并且是区分大小写的匹配时才能有效地使用索引。此外,虽然 /^a/、/^a.*/ 和 /^a.*$/ 匹配等效字符串,但它们具有不同的性能特征。如果存在适当的索引,则所有这些表达式都使用索引;但是,/^a.*/ 和 /^a.*$/ 速度较慢。 /^a/ 匹配前缀后可以停止扫描。

    【讨论】:

      【解决方案3】:

      您可以做的事情并不多。你有一百万个元素中的一半,你正在对所有元素进行全面扫描。这需要时间并不奇怪。此外,您的搜索基于可以在字符串中的任何位置的正则表达式。所以在这种情况下索引不能帮助你。

      如果您的搜索基于单词,您可以尝试从字符串创建数组。例如字符串'Salvador Domingo Dali' 将被转换为['Salvador', 'Domingo', 'Dali']。如果您要在此数组上添加索引并尝试查找 'Dali',则搜索将利用此索引。

      附:数据库和索引不是灵丹妙药。有时您需要更好的逻辑来处理大量数据。

      【讨论】:

      • 我第一次使用数组来存储名称,正如您所说并为该数组添加了索引,但发现它非常昂贵。这次搜索花了 3-10 分钟,所以我将其更改为单列,以减少时间,但这仍然只是我的测试数据。生产将有更多的数据..请帮助一些解决方案
      • 您能否展示您对阵列解决方案的解释以及您文档中的相关示例?
      猜你喜欢
      • 2018-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 2023-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多