【问题标题】:Analytics in ElasticsearchElasticsearch 中的分析
【发布时间】: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 的查询提供给定的可扩展性和性能。 任何帮助将不胜感激。

【问题讨论】:

    标签: hadoop elasticsearch aggregate olap-cube


    【解决方案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"
    • 我认为它缺少顶级聚合的名称;查看编辑的示例
    猜你喜欢
    • 2012-10-01
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-16
    • 2011-07-19
    • 2014-02-15
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多