小试牛刀ElasticSearch大数据聚合统计

SGA: allocation forcing component growth分析

        ElasticSearch相信有不少朋友都了解,即使没有了解过它那相信对ELK也有所认识E即是ElasticSearch。ElasticSearch最开始更多用于检索,作为一搜索的集群产品简单易用绝对是一个非常不错的选择,其实本人早在ElasticSearch v0.2的时候就使用,一转眼数年过去现在都7.X了。

        其实ElasticSearch除了提供强大的集群化搜索服务外,它提供一个aggregation功能会再一次让你受到它的强大,aggregation是一个数据统计汇总功能,表面上这功能在关系数据库上也可以做,但结合分词建维度就更能体现出它的灵活之处。

关系数据库问题

        拿产品订单为例,它有产品分类,不同的规格,销售人,客户和地区等;然而这些信息在设计上都是归纳到不同的表中,如果要针对这些不同的信息来统计订单销售情况那相信是一件非常繁琐和效率极其低下的工作(先不说数据数千万了上亿或更大规模,就算几十上百万数据这个关系数据的SQL查询也够受了)。即便可以把数据抽取并归纳起来做统计,但随着新的数据维度增加新的维度字段重新调用。

无维度字段?

        在数据统计每个维度都对一个信息列来存储,这样加入维度必须就需要添加信息列。如果用一个字段存储所有维度信息呢?显然这种想法在传统关系数据库中也不可能的,因为无法做表的关联和维度区分,其实不要说传统数据库很多数据库都无法在一个字符中拆分出不同的维度出来,除非加入程序来切分,但这种法在数据规模大的情况必然是不可取的!

        如果用一个字段就能存储所有维度,那就意味着以后加入新的维度数据也无须调整结构和程序就实现新维护度数据的统计处理。这看上去多么美好,似乎也很难实现,但ElasticSearch能解决这一问题。

试验

        首先ElasticSearch是一个搜索引擎,它最擅长的工作是对内容进行分词并构建索引;在这机制下可以对一个字段的信息进行拆分并存储到索引上。通过这一特性同样可以把一个字段的信息切分成N个维度的信息,然后存储到索引;只要有了单一的维度索引那接下来针对不同维护的汇总统计就简单了。

在单节点的ElasticSearch上创建了5千万条产品销售数据;然后Tag字段存储对应的维度信息,每个维度通过/来区分,分别有:customer,employee,country和category.有了这些信息,接下来的工作是尝试使用Aggr功能来完成相应的汇总

var query = db.Index.CreateQuery();
query.Prefix("Tag", "客户");
var aggs = db.Index.CreateAggs("customer_group", 
     Elasticsearch.Search.AggsType.terms, "Tag");
aggs.SubAggs("sum_quantity", Elasticsearch.Search.AggsType.sum, "Quantity");
aggs.SubAggs("sum_total", Elasticsearch.Search.AggsType.sum, "Total");
aggs.Size(5);
aggs.Query = query;
var items = await aggs.Execute<OrderRecord>();

代码并不复杂,查询Tag标签存在customer的数据,并对它们进行一个分组,最后再汇总出对应的Quantity和Total信息;最后获取排在最前面的5条数据。

效率

        ElasticSearch做这方面的效率怎样呢?部署在一个节点上,分别汇总了客户,国家和员工。

.NET Core部署到linux(CentOS)最全解决方案,进阶篇(Supervisor+Nginx)

5千万条(单机单节点)

5千万条(单机双节点)

 这个时间是在不停更新索引下同时做统计的结果,当在索引不更新的情况其二次处理效率会高上几倍。

静态历史数据

        上面绍了ElasticSearch对大数据一个聚合效率做了一个测试,那测试是基于动态数据测试,即在聚合测试的过程中同时大量更新索引数据;接下来做的测试则是针对固定的历史数据,在聚合测试过程中不进行数据更新。

测试数据环境

        5千万条件产品销售数据,分布在2000-2020间,所有数据部署在单机双节点的服务中。

测试过程

        分别汇总每一年的员工,国家和分类数据,并显示最前面的3条记录。

int top = 3;
for (int i = 2000; i < 2020; i++)
{
    DateTime start = new DateTime(i, 1, 1);
    DateTime end = new DateTime(i + 1, 1, 1);
    var result = await db.AggsTag("国家", top, start, end, null);
    Console.WriteLine($"|  {result.Title} use {result.UseTime:###,###.00}ms");
    Console.WriteLine($"|-{"".PadLeft(89, '-')}|");
    foreach (SummaryItem item in result.Items)
    {
        Print(item);
    }

    result = await db.AggsTag("分类", top, start, end, null);
    Console.WriteLine($"|  {result.Title} use {result.UseTime:###,###.00}ms");
    Console.WriteLine($"|-{"".PadLeft(89, '-')}|");
    foreach (SummaryItem item in result.Items)
    {
        Print(item);
    }

    result = await db.AggsTag("员工", top, start, end, null);
    Console.WriteLine($"|  {result.Title} use {result.UseTime:###,###.00}ms");
    Console.WriteLine($"|-{"".PadLeft(89, '-')}|");
    foreach (SummaryItem item in result.Items)
    {
        Print(item);
    }
}

测试结果

 从测试结果来看效率非常出色,每个年分类聚合统计所损耗的时候大概在0.1秒。

SwiftUI 中一些和响应式状态有关的属性包装器的用途

给TA买糖
共{{data.count}}人
人已赞赏
经验教程

CWE 4.3:强化你的数据自我保护能力

2021-1-21 10:41:00

经验教程

SGA: allocation forcing component growth分析

2021-1-21 11:11:00

⚠️
免责声明:根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。 本站为个人博客非盈利性站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途,网站会员捐赠是您喜欢本站而产生的赞助支持行为,仅为维持服务器的开支与维护,全凭自愿无任何强求。本站部份代码及教程来源于互联网,仅供网友学习交流,若您喜欢本文可附上原文链接随意转载。
无意侵害您的权益,请发送邮件至 momeis6@qq.com 或点击右侧 私信:momeis 反馈,我们将尽快处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
今日签到
有新私信 私信列表
搜索