有效地计算SQL中的重要术语

时间:2016-06-02 17:03:06

标签: sql elasticsearch query-optimization aggregation significant-terms

前一段时间我被介绍给ElasticSearch significant terms aggregation,并对这个衡量标准的优秀和相关程度感到非常惊讶。对于那些不熟悉它的人来说,它是一个非常简单的概念 - 对于给定的查询(前景集),给定的属性根据背景集的统计显着性进行评分。

例如,如果我们要查询英国交通警察中最重要的犯罪类型:

C = 5,064,554 -- total number of crimes
T =    66,799 -- total number of bicycle thefts
S =    47,347 -- total number of crimes in British Transport Police
I =     3,640 -- total number of bicycle thefts in British Transport Police
  

通常,自行车盗窃只占犯罪的1%(66,799 / 5,064,554),但对于处理铁路和车站犯罪的英国交通警察来说,7%的犯罪(3,640 / 47,347)是自行车盗窃。频率增加了7倍。

"自行车盗窃的重要性"将是[(I/S) - (T/C)] * [(I/S) / (T/C)] = 0.371...

其中:

  • C 是集合中所有文档的编号
  • S 是与查询匹配的文档数
  • T 是具有特定字词
  • 的文档数
  • 是与 S T
  • 相交的文档数量

由于实际原因(我拥有大量数据以及巨大的ElasticSearch内存要求),我希望在SQL中或直接在代码中实现重要的术语聚合。

我一直在寻找一些方法来潜在地优化这种查询,特别是降低内存需求和提高查询速度,但代价是一些错误余量 - 但到目前为止我还没有破解了它。在我看来:

  • 变量 C S 很容易缓存或查询。
  • 变量 T 可以从Count-Min Sketch派生而不是查询数据库。
  • 然而,变量 I 似乎无法使用 T 中的Count-Min Sketch获得。

我也在查看MinHash,但从描述中看来它似乎无法在这里应用。

有没有人知道一些有助于解决这个问题的聪明算法或数据结构?

2 个答案:

答案 0 :(得分:10)

我怀疑SQL impl会更快。 Lucene提前保持C和T的值。 S是从查询结果派生的简单计数,我使用O(1)数据结构查找。主要成本是在所选字段中观察到的每个术语的许多T查找。使用min_doc_count通常有助于大幅减少这些查找的数量。

  

出于实际原因(我拥有大量数据和巨大的ElasticSearch内存要求

您是否考虑过使用doc值更好地管理elasticsearch内存?见https://www.elastic.co/blog/support-in-the-wild-my-biggest-elasticsearch-problem-at-scale

答案 1 :(得分:1)

当前景集足够小时,可以采用有效的解决方案。然后您可以负担处理前景集中的所有文档。

  1. 收集所选字段前景集中出现的所有字词集{ X k }及其频率{ f k }在前景集中。

  2. 对于每个 X k

    • 计算 X k 的重要性为( f k - F k )*( f k / F k ),其中 F k = T k / C X 背景集中的 k
  3. 选择具有最高显着性值的术语。

  4. 但是,由于这种方法的简单性,我想知道ElasticSearch是否已包含该优化。如果它没有 - 那么它很快就会出现!