【问题标题】:What is the fastest way to filter documents by flags?按标志过滤文档的最快方法是什么?
【发布时间】:2018-06-28 06:16:01
【问题描述】:

我的索引中的文档可以有不同的预过滤标志,例如INVALIDPRIVATE 等。每个标志都涵盖文档的不同方面,因此它们彼此不相关,即它们实际上是布尔值。

目标:在运行评分查询之前找到过滤这些文档的最快方法。

选项:

  • 为每个标志创建一个字段为Boolean Field,以便可以通过真或假过滤它们
  • 为每个标志创建一个字段为Keyword Field,这样如果条目有值或为NULL,它们可以通过Exists Query 过滤。
  • 为所有标志创建一个字段为Text Field,以便可以通过常规Match Query 过滤它们
  • 任何其他我没有想到的方法。

感谢您的任何建议!

【问题讨论】:

  • 显然是第一个选项
  • @Val 我测试了这个......你是对的。谢谢。请参阅下面的答案。
  • 干得好,感谢您分享您的发现!

标签: elasticsearch


【解决方案1】:

所以,我对此进行了测试,得到了以下结果:

TL;DR:如果您需要一次查询多个标志,请使用布尔字段作为标志。如果您只需要查询一个标志值,则使用您喜欢的任何值。


索引中的文档:10.000.000

标志字段:

  • nullFlag,可能的值:null"exists",查询:Exists Query
  • booleanFlag,可能的值:truefalse,查询:Term Query
  • textFlag,可能的值:VALIDINVALIDDUMMY_FLAG1DUMMY_FLAG2DUMMY_FLAG3,查询:Match Query

注意事项:

  • 所有用于测试的标记都均匀分布,~50/50。总是出现“虚拟标志”以使该字段更“真实”。
  • 节点查询缓存已通过 index.queries.cache.enabled: false 禁用。
  • 首次运行可能会因 JVM 启动而变慢。我确认查询缓存已禁用。
  • 查询由本机 Java QueryBuilder 提供,忽略 adjust_pure_negativeboost
  • 我不知道查询是否最佳甚至正确。

结果:

  • Exists Query 似乎是最慢的
  • 通过Term Query 过滤布尔值和通过Match Query 检查文本标志似乎没有什么不同,如果您只过滤一个标志。
  • 如果您要过滤多个标志,则通过 Term Query 的布尔值更快。
  • 我不知道查询是否最佳甚至正确。

测试:

booleanFlag - 词条查询

查询:

{
  "bool" : {
    "filter" : [
      {
        "term" : {
          "booleanFlag" : {
            "value" : true,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     91ms |    4998613
2     |     45ms |    4998613
3     |     46ms |    4998613
4     |     45ms |    4998613
5     |     45ms |    4998613

查询:

{
  "bool" : {
    "filter" : [
      {
        "term" : {
          "booleanFlag" : {
            "value" : false,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     97ms |    5001387
2     |     45ms |    5001387
3     |     45ms |    5001387
4     |     48ms |    5001387
5     |     45ms |    5001387

nullFlag - 存在查询

查询:

{
  "bool" : {
    "filter" : [
      {
        "bool" : {
          "must" : [
            {
              "exists" : {
                "field" : "nullFlag",
                "boost" : 1.0
              }
            }
          ],
          "adjust_pure_negative" : true,
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     99ms |    4999305
2     |     53ms |    4999305
3     |     53ms |    4999305
4     |     53ms |    4999305
5     |     54ms |    4999305

查询:

{
  "bool" : {
    "filter" : [
      {
        "bool" : {
          "must_not" : [
            {
              "exists" : {
                "field" : "nullFlag",
                "boost" : 1.0
              }
            }
          ],
          "adjust_pure_negative" : true,
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |    145ms |    5000695
2     |    107ms |    5000695
3     |    104ms |    5000695
4     |    104ms |    5000695
5     |    107ms |    5000695

textFlag - 匹配查询

查询:

{
  "bool" : {
    "filter" : [
      {
        "match" : {
          "textFlag" : {
            "query" : "VALID",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     87ms |    4998937
2     |     43ms |    4998937
3     |     44ms |    4998937
4     |     43ms |    4998937
5     |     42ms |    4998937

查询:

{
  "bool" : {
    "filter" : [
      {
        "match" : {
          "textFlag" : {
            "query" : "INVALID",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     89ms |    5001063
2     |     48ms |    5001063
3     |     43ms |    5001063
4     |     43ms |    5001063
5     |     43ms |    5001063

-- 使用多个标志进行测试 ------

textFlag - 使用 2 个标志匹配查询

查询:

{
  "bool" : {
    "filter" : [
      {
        "match" : {
          "textFlag" : {
            "query" : "VALID DUMMY_FLAG1",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |    151ms |   10000000
2     |    105ms |   10000000
3     |    106ms |   10000000
4     |    105ms |   10000000
5     |    107ms |   10000000

booleanFlag - 带有 2 个标志的术语查询

查询:

{
  "bool" : {
    "filter" : [
      {
        "term" : {
          "booleanFlagOne" : {
            "value" : true,
            "boost" : 1.0
          }
        }
      },
      {
        "term" : {
          "booleanFlagTwo" : {
            "value" : false,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |    138ms |    2500645
2     |     84ms |    2500645
3     |     84ms |    2500645
4     |     83ms |    2500645
5     |     86ms |    2500645

--更多测试------

nullFlag - 存在查询(没有不必要的双布尔查询)

查询:

{
  "bool" : {
    "filter" : [
      {
        "exists" : {
          "field" : "nullFlag",
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     93ms |    5000779
2     |     42ms |    5000779
3     |     43ms |    5000779
4     |     42ms |    5000779
5     |     44ms |    5000779

查询:

{
  "bool" : {
    "must" : [
      {
        "exists" : {
          "field" : "nullFlag",
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |     88ms |    5000779
2     |     43ms |    5000779
3     |     42ms |    5000779
4     |     43ms |    5000779
5     |     42ms |    5000779

查询:

{
  "bool" : {
    "must_not" : [
      {
        "exists" : {
          "field" : "nullFlag",
          "boost" : 1.0
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}

结果:

Run   |     Time |       Hits
1     |    139ms |    4999221
2     |     96ms |    4999221
3     |     98ms |    4999221
4     |     95ms |    4999221
5     |     94ms |    4999221

【讨论】:

  • 干得好。如果您还有一些时间进行测试,如果您省略不必要的第二个布尔查询,我会对第二个选项(存在查询)发生什么感兴趣。只是 bool -> filter -> 存在于第一个和 bool -> must_not -> 存在于第二个实际上就足够了。
  • @Slomo 很酷,这使查询更快。请参阅“更多测试”。谢谢你的建议。 Java API 似乎没有提供“否定过滤器”,即“获取字段为空的所有内容”,所以我无法测试。
猜你喜欢
  • 1970-01-01
  • 2015-02-27
  • 1970-01-01
  • 2011-06-05
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-17
相关资源
最近更新 更多