Elasticsearch 中的分析

Posted

技术标签:

【中文标题】Elasticsearch 中的分析【英文标题】:Analytics in Elasticsearch 【发布时间】:2014-09-17 02:59:34 【问题描述】:

我正在处理事件分析,我使用 hadoop 处理日志并将一些结果存储在 mysql 中。由于日志每天都在不断出现,因此由于可扩展性问题,这现在不起作用。

我们需要显示每年、每月、每周、每天、每小时的统计数据以及过滤功能 我们的样本可以增长到 10 万用户,每个用户每小时使用 20 个网站 100,000(用户)* 20(唯一网站)* 2(位置)* 24(小时)= 96,000,000(每天最多 9600 万条记录)

我们的表格看起来像event_src_id、时间、用户、网站、位置、一些统计数据

一些查询示例是

1) select website, sum(stats), count(distinct(user_id)) from table group by website;
2) select website, sum(stats), count(distinct(user_id)) from table where YEAR(Time) = 2009 group by website, MONTH(Time);
3) select website, sum(stats), count(distinct(user_id)) from table group by website where event_src_id=XXXXXXXXXXX;
4) select website, sum(stats), count(distinct(user_id)) from table group by website where time > 1 jan 2014 and time <=31 jan 2014;
5) select website, location, sum(stats), count(distinct(user_id)) from table group by website, location;
6) select website, sum(stats) as stats_val from table group by website order by stats_val desc limit 10;
   select location, sum(stats) as stats_val from table group by location order by stats_val desc limit 10;
7) delete from table where event_src_id=XXXXXXXXXXX; (may delete all 96M records)

我尝试了 Hadoop 弹性搜索,它似乎可以修复插入部分,我更担心阅读部分。 聚合框架似乎给了一些希望,但我无法按照查询一工作。如何同时分组和求和和区分? 我如何才能最好地将 Elasticsearch 与 Hadoop 结合使用,并为基于 OLAP 的查询提供给定的可扩展性和性能。 任何帮助将不胜感激。

【问题讨论】:

【参考方案1】:

首先,我认为将 ElasticSearch 用于类似 OLAP 的查询并不是一个好主意。我建议您使用一些支持您指定的 sql 的类似 Dremel 的技术(Impala、TEZ、Storm 等)。它有一些优点,例如:

您不必将数据从 Hadoop 传输到 ElasticSearch。 你可以使用sql 您不必关心从 ElasticSearch 查询答案中解析 json。

不要误会我的意思,我喜欢 ElasticSearch/Logstash/Kibana,但用于日志收集和可视化。当然可以进行一些高级查询,但是我在个人项目中发现了一些限制。

另外考虑使用 Kibana,它是 ElasticSearch 中数据统计的绝佳工具,你可以用它做很多事情。

以下是您要求的一些查询示例(我没有测试过):

1)


  "aggs": 
    "website": 
      "terms": 
        "field": "website"
      ,
      "aggs": 
        "sum_stats": 
          "sum": 
            "field": "stats"
          ,
          "aggs": 
            "distinct_user": 
              "cardinality": 
                "field": "user_id",
                "precision_threshold": 100
              
            
                    
        
      
    
  

2-6 是相似的,使用 1) 中的东西和不同的filters 像这样:


  "aggs": 
    "your_filter": 
      "filter": 
        "term": "event_src_id" : "XXXXXXXXXXX"
      
    ,
    "aggs": 
      "website": 
        "terms": 
          "field": "website"
        ,
        "aggs": 
          "sum_stats": 
            "sum": 
              "field": "stats"
            ,
            "aggs": 
              "distinct_user": 
                "cardinality": 
                  "field": "user_id",
                  "precision_threshold": 100
                
              
            
          
        
      
    
  

7) 删除​​很简单

    "query" : 
        "term" :  "event_src_id" : "XXXXXXXXXXX" 
    

【讨论】:

是的,使用 HDFS 似乎是正确的,但是任何一个都可以用于实时吗? 目前因 AggregationInitializationException 而失败[[sum] 类型的聚合器 [sum_stats] 无法接受子聚合]; 只需将 agg 转换为 sum (sum_stats) 与不同的用户,如下所示: "aggs": "website": "terms": "field": "website" , "aggs": "distinct_user": "cardinality": "field": "user_id", "precision_threshold": 100 , "aggs": "sum_stats": "sum": "field": "stats" 您可以实时使用 HDFS。你是对的,这并不理想,但它是可能的。我也在考虑与您类似的架构-logstash 将数据放入 ElasticSearch,而不是在 Kibana/ElasticSearch 中将其可视化,然后将数据从 ES 批量下载到 HDFS 以用于 OLAP 目的。这是一个关于近实时 HDFS 的有趣幻灯片分享 - slideshare.net/tobym/data-pipeline-at-tapad。这个话题对我来说真的很有趣,所以如果你想更深入地讨论它,你可以给我写一封电子邮件。 不,它没有给出 sum_stats,也只产生了 10 个网站,我怎样才能得到所有的网站(使用分页)?酷,你能用电子邮件更新你的个人资料,以便我可以给你发电子邮件吗?上面幻灯片中使用的堆栈是 vertica。【参考方案2】:

如何同时分组、求和和区分

聚合可以有sub-aggregations。

首先,组功能对应于terms aggregation 和(有时)top_hits aggregation。 其次,有一个sum aggregation,一个简单的统计指标聚合。 最后,在这种情况下,您使用 distinct 是执行 count(distinct),它对应于 cardinality aggregation,根据您的需要可以是近似值或精确值。

7) 从表中删除 event_src_id=XXXXXXXXXXX; (可能会删除所有 96M 记录)

您可以使用delete by query api,但请注意删除文档的百分比很高; Lucene 和 Elasticsearch 并未为此进行优化,您会因删除数据中的标记而产生开销。

示例

按网站从表组中选择网站、sum(stats)、count(distinct(user_id))

GET /_search

   "aggs": 
      "website_stats": 
        "terms": 
           "field": "website"
        ,
        "aggs": 
           "sum_stats": 
             "sum": 
               "field": "stats"
             
           ,
           "count_users": 
             "cardinality": 
               "field": "user_id"
            
          
        
      
   

select website, sum(stats), count(distinct(user_id)) from table where YEAR(Time) = 2009 group by website, MONTH(Time)

GET /_search

   "query": 
     "filter": 
       "range": 
           "Time": 
              "gt": "2009-01-01 00:00:00",
              "lt": "2010-01-01 00:00:00"
           
       
     
   ,
   "aggs": 
      "monthly_stats" 
        "terms": 
           "field": "website"
        ,
        "aggs": 
           "months": 
              "date_histogram": 
                "field": "Time",
                "interval": "month"
              ,
              "aggs" : 
                "sum_stats": 
                  "sum": 
                    "field": "stats"
                  
                ,
                "count_users": 
                  "cardinality": 
                    "field": "user_id"
                
              
            
          
        
      
   

【讨论】:

为了完整起见,您能否分享一些 1 到 7 的查询示例? 添加了两个示例——希望这足以扩展到其他查询 因 AggregationInitializationException 失败[[sum] 类型的聚合器 [sum_stats] 不能接受子聚合]; hmmm "sum_stats" 没有子聚合,"months" 有两个子聚合:"sum_stats" 和 "count_users" 我认为它缺少***聚合的名称;查看编辑的示例

以上是关于Elasticsearch 中的分析的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch:如何分析和优化 Elastic 部署的存储空间

Elastic Search 基本操作

Elastic Stack(ElasticSearch Kibana 和 Logstash) 实现日志的自动采集搜索和分析

elastic分页查询scroll

elasticSearch-mappings(映射,分析)

Logstash+elasticsearch+elastic+nignx