Elasticsearch适合存词频数据吗
安瑞哥是码农
2022-10-19 18:05:00
数据库开发技术
原创
这是讨论群里一位小伙伴提出来问我的一个问题,我直接回答说:当然适合,但是好像这个回答他并不很满意,马上补了一句:展开说说呢,实现思路是怎么样的呢?
Emmm... 这不,针对这个问题,我专门来写这篇文章来展开,是不是够有诚意。
1.
其实对于这种类似解决方案的问题,光是回答一个好还是不好,合适还是不合适确实是远远不够的,这个问题就好比你问:学大数据好找工作吗? 有人回答好找,那也一定有人说很难找,至于原因,则需要根据具体场景展开来说,否则,光是这样的答案没有指导意义。
我从16年开始接触ES,17年开始用于生产,一直到今天,大部分项目都有它活跃的身影,因此自认为还是有些发言权的。
Elasticsearch应该是众多优秀开源数据库产品中,非常耀眼的一颗明星,从诞生之日开始就一直受到追捧,很多人对它的认知源于全文索引引擎,但却忽略了它作为数据库属性强大的数据聚合分析能力。
既然ES提供了强大聚合能力,那么用它来做一个词频统计,那绝对是不在话下的,比如,我为了演示上次那个数据倾斜的案例,就把我提供给大家的那份数据集,直接全部写入到ES中,然后对我感兴趣的字段做keyword索引。
再利用ES强大的聚合查询能力,一下子就找到了用户访问最多的目标ip,并以此为依据来演示数据倾斜,其请求如下:
查询结果如下:
从这个查询结果就可以知道,每个target_ip被访问了多少次(一个文档记录就代表一次),看到这个查询效果,你是不是瞬间觉得:我擦,这也太方便了吧,那我以后所有对数据的聚合统计分析岂不是只需要将原始数据直接灌到ES,然后通过各种聚合查询就能瞬间查出来。
如果在生产上你这么玩,那一定是灾难的开始,
因为没有哪个软件能够一劳永逸的解决所有问题
,ES当然也不能免俗。
ES最大缺点在于:随着数据量的剧增,其单纯的查询效率还好,但是聚合效率会随着数据量的增加而不断下降。
原因在于:
聚合不同于一般的条件查询,一般条件查询直接通过走索引就能以很低的时间复杂度把目标数据给取出来,而聚合有个额外排序和计算的过程
。
以上面提到的这个为例,我们对target_ip这个字段进行词频统计,对于ES而言,为了保证查询效率,必须要指定一个size(不指定的话,默认为10),这个size就是我们常说的top N。
这样做的根本目的在于保证聚合效率,ES的内部逻辑是这样的:
比如定size为100,那么ES的第一步是先在该索引的各个分片中取每个分片的top 100的target_ip;第二步再找到一个【聚合节点】,再把所有分片的top 100的target_ip再次统计,最后取出最终的top 100的target_ip。
2.
如果你理解了这个过程后会发现,ES聚合的结果其实是个近似值(
因为局部的top N可能不一定是全局的top N,不信,你可以做个试验验证一下
),是的,你没有看错,就是近似值,尤其当数据量越大的时候,那么这个值可能的近似程度越高,原因在于:需要对效率做妥协。
看到这里,你是不是想说:我去,这么垃圾的吗?既然聚合结果不准,那我还用它干嘛?
其实也没有必要那么悲观,对于ES来说,任何一个聚合出来的结果,是不是真的为近似值,以及近似程度有多高,我们是完全
可以从聚合结果看出来
的。
如何看?比如上面这个例子,我们看这里:
这里有两个指标,官方的解释是这样的:
看不懂对不对,用我这么多年来对ES的使用经验的理解是这样的:
第一个指标意思是:目前可能因为哪些文档没有参加聚合而导致结果不准,注意这里只是有可能不准,也就是说,如果这个数字如果为0,那么本次聚合结果一定准确的,但是如果大于0,也只能说明聚合结果可能存在误差。
第二个指标意思是:本次聚合有没有参与其中的各个分片的文档总数。
总之一句话理解就是:
这两个指标的值如果都为0,则证明聚合结果一定是准确的,而如果大于0,那么也不代表聚合结果就不准确,只是这两个数值如果越大,则证明聚合结果为近似值的可能性越高
。
以上,是我对80万数据量的聚合情况,但是如果我把数据量增加到千万级别呢?
再来看下同样的聚合条件,得出的结果是什么样的:
可以看到,当数据量为两千多万的时候,这个两个指标的值不再为0,也就是说,当前的聚合结果可能是个近似值。
那如果你问:
基于同样的数据量,我想让聚合结果更准确该怎么办?
增加size值大小,之前不是100嘛,经过我的实验,当我增加到5000时,这两个指标就都为0了:
但是与之付出的代价就是:
查询时间变慢,有查询超时的风险
。
所以看到这里,你是不是对ES适不适合用来统计词频有了个大概的理解,肯定是可以,只是在使用的时候,你需要知道它的优势和瓶颈分别在哪些地方。
3.
如果项目数据量小,那一切都好办,以上提到的情况都不存在,但是如果数据量巨大,这里就需要涉及到软件设计、或者说架构设计的能力,玩法可能会完全不一样。
同是一款软件,不同的人对其理解是不一样的,因为不同使用者对其原理掌握的深度,以及实践的深度是不一样的,可能面对同一个应用场景,有的人觉得ES一定可以胜任,而有的人则认为不行。
最后,还是给一个指导性结论:
如果基于我提供的实战项目数据集,不对数据做任何预计算处理,只用ES对其做粗暴的聚合统计,经过我的粗略验证,单层聚合的数据量上限可以到达约5000W应该没有问题(当然,具体还根据你机器的硬件配置有关系),但是如果还想支持双重或者多重嵌套聚合,那么查询效率会急剧下降,最好单个分片数据量控制在千万以内。
而对于更大的数据量,仅仅依赖ES的单个索引肯定是行不通的,要么数据量达到一定阈值后,分索引。要么利用计算引擎,将数据在进入ES前进行预统计,来减少写入ES的总数据量,尽可能减少数据在ES端【运算】的时间。
------------------------------------------------------------------
以上就是我对这个问题的思考和回答,怎么样三胖,你还满意不?
我这有一个高质量的大数据学习讨论群,不怎么扯淡、偶尔活跃气氛、大部分时间都在讨论技术,你在群里的几乎任何大数据相关的问题,都可以得到解答,要不要进来试试呢?拉你进群啊
...
打工人,皮实一点
大数据项目——倾斜数据的分区优化