2016-07-14 30 views
1

我是在弹性搜索中对指标名称建立索引。度量名称的格式为foo.bar.baz.aux。这是我使用的索引。术语聚合(实现分层刻面)查询性能缓慢

{ 
    "index": { 
     "analysis": { 
      "analyzer": { 
       "prefix-test-analyzer": { 
        "filter": "dotted", 
        "tokenizer": "prefix-test-tokenizer", 
        "type": "custom" 
       } 
      }, 
      "filter": { 
       "dotted": { 
        "patterns": [ 
         "([^.]+)" 
        ], 
        "type": "pattern_capture" 
       } 
      }, 
      "tokenizer": { 
       "prefix-test-tokenizer": { 
        "delimiter": ".", 
        "type": "path_hierarchy" 
       } 
      } 
     } 
    } 
} 

{ 
    "metrics": { 
     "_routing": { 
      "required": true 
     }, 
     "properties": { 
      "tenantId": { 
       "type": "string", 
       "index": "not_analyzed" 
      }, 
      "unit": { 
       "type": "string", 
       "index": "not_analyzed" 
      }, 
      "metric_name": { 
       "index_analyzer": "prefix-test-analyzer", 
       "search_analyzer": "keyword", 
       "type": "string" 
      } 
     } 
    } 
} 

上述指标的度量标准名称创建下列条款foo.bar.baz

foo 
bar 
baz 
foo.bar 
foo.bar.baz 

如果我有一堆指标,像下面

a.b.c.d.e 
a.b.c.d 
a.b.m.n 
x.y.z 

我要编写一个查询抢令牌的第n级。在上面的例子中

for level = 0, I should get [a, x] 
for level = 1, with 'a' as first token I should get [b] 
       with 'x' as first token I should get [y] 
for level = 2, with 'a.b' as first token I should get [c, m] 

我想不出任何其他方式,除了写术语聚合。要找出a.b的二级令牌,下面是我提出的查询。

time curl -XGET http://localhost:9200/metrics_alias/metrics/_search\?pretty\&routing\=12345 -d '{ 
     "size": 0, 
     "query": { 
     "term": { 
      "tenantId": "12345" 
     } 
     }, 
     "aggs": { 
      "metric_name_tokens": { 
       "terms": { 
        "field" : "metric_name", 
        "include": "a[.]b[.][^.]*", 
        "execution_hint": "map", 
        "size": 0 
       } 
      } 
     } 
    }' 

这会导致下面的问题。我解析输出并从那里抓取[c,m]。

"buckets" : [ { 
    "key" : "a.b.c", 
    "doc_count" : 2 
    }, { 
    "key" : "a.b.m", 
    "doc_count" : 1 
} ] 

到目前为止好。该查询适用于大多数租户(请注意上面的tenantIdterm查询)。对于有大量数据(大约1Million)的某些租户来说,表现确实很慢。我猜测聚合的所有术语都需要时间。

我想知道术语聚合是否是这种数据的正确选择,并且还在寻找其他可能的查询类型。

+0

我不清楚你需要什么。你需要计数吗?或者你需要c和m吗?或者您是否需要包含以下文件:a.b.c.d.e - a.b.c.d - a.b.m.n? –

+0

我只需要c和m。 – Chandra

+0

@JettroCoenradie我只需要c和m。基本上什么是给定前缀的下一级可能令牌。 – Chandra

回答

1

几点建议:

  • “镜子”的聚合过滤器在查询部分水平以及。因此,对于a.b.匹配,请使用下列为查询并保持相同的AGGS部分:
"bool": { 
    "must": [ 
    { 
     "term": { 
     "tenantId": 123 
     } 
    }, 
    { 
     "prefix": { 
     "metric_name": { 
      "value": "a.b." 
     } 
     } 
    } 
    ] 
} 

甚至使用regexp具有相同的正则表达式作为凝聚部。通过这种方式,聚合将不得不评估较少的桶,因为到达聚合部分的文档将更少。 你提到regexp对你来说效果更好,我最初的猜测是prefix会表现更好。

  • "size": 0从聚合变为"size": 100。经过测试你提到这没有任何区别
  • 删除"execution_hint": "map"并让Elasticsearch使用默认值。经过测试,你提到默认的execution_hint表现更差。
  • 我唯一能想到的其他事情就是通过在索引时移动它来减轻搜索时间的压力。我的意思是:在索引时,在你自己的应用程序或者你正在使用的任何索引方法中,将文本分割为程序化索引(而不是ES),并将索引中的每个元素索引到一个单独的字段中。例如a.bfield2,a.b.cfield3等等。这对于同一个文件。然后,在搜索时间,根据搜索文本的内容查看特定字段。然而,这个想法在ES之外需要一些额外的工作。

从以上所有建议中,第一个建议的影响最大:查询响应时间从23秒提高到了11秒。

+0

根据你对字符串abcde,abxy的建议,我会分别索引index [a],[ab],[abc],[abcd],[abcde],[abx],[abxy],然后如何搜索获取跟随前缀ab的所有令牌? – Chandra

+0

对于文档,您应该具有以下结构:'{“tenantId”:123,“metric_name1”:[“a”,“x”],“metric_name2”:[“ab”,“xy”],“metric_name3”: [ “ABC”, “ABM”, “XYZ”], “metric_name4”:[ “ABCD”, “abmn”], “metric_name5”:[ “ABCDE”]}'。所有'metric_name *'字段将使用'关键字'分析器或任何不会分裂它的东西。查询本身(因为您希望允许用户搜索'ab * .d'而不仅仅是'前缀'查询)应该与''query_string“类似:{ ”default_field“:”metric_name *“, ”查询“:”ab * .d“ }'。 –

+0

的聚合将是这样的,虽然' “AGGS”:{ “metric_name_tokens”:{ “术语”:{ “场”: “metric_name3”, “大小”:0 } } }'。所以,基本上,对于'a.b。*。d'搜索,您只对'a.b.'后面的内容感兴趣。你会使用'metric_name3'字段(具有三个层次结构的字段)。但我很想知道从query_string查询中看到了什么样的性能。聚合部分会更轻。 –