数据在ElasticSearch,需要对数据进行数据统计分析方法,怎么做

2262人阅读
网站数据(8)
&&& 按照惯例,我们先来看看es的介绍:
&&& ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎。设计用于中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。支持通过HTTP使用JSON进行数据索引。
&&& 我们建立一个网站或应用程序,并要添加搜索功能,令我们受打击的是:搜索工作是很难的。我们希望我们的搜索解决方案要快,我们希望有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP的索引数据,我们希望我们的搜索服务器始终可用,我们希望能够一台开始并扩展到数百,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。Elasticsearch旨在解决所有这些问题和更多的。
&&& &!--以上内容解释权归百度所有--&
&&& 我们接着logstash那篇博文来讲,我们的output输出是以控制台stdout打印的形式展现出来的,那么今天我们就以输出为es的形式来探讨!
&&& 官网:http://www.elasticsearch.org/
&&& 1、安装es
&&& 2、解压
&&& 3、测试。切换到elasticsearch安装目录下,再命令行输入:
&&& bin/elasticsearch 命令,如果出现started字样的英文,则可以判定es安装启动成功!当然我们可以再浏览器上输入http://127.0.0.1:9200/ 如果出现有关es的配置信息,则说明启动成功!
&& 然后,我们联系logstash,从logstash中拿数据,作为es的搜索!只需配置logstash.conf文件即可
&& input {
&& &redis {
&& &host =& &127.0.0.1&
&& &data_type =&&list&
&& &key =& &mylogstash&
&& &type =& &redis-input&
output {&&&&
&&&&&& stdout { codec =& rubydebug }&&
&&&&&& elasticsearch { host =& localhost }
& 大家可能注意到了,logstash.conf的变化,只是添加了一行代码:elasticsearch { host =& localhost }
& 代表logstash处理的数据已经输出到了es搜索引擎中,此时我们开启redis,logstash,elasticsearch三个组建之后,再浏览器中输入http://127.0.0.1:9200/,则会显示保存再redis队列中的相关信息。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:106206次
积分:1824
积分:1824
排名:千里之外
原创:66篇
转载:24篇
评论:25条
(1)(4)(3)(30)(10)(43)数据在ElasticSearch,需要对数据进行统计分析,怎么做? - 知乎4被浏览1270分享邀请回答/2016/04/11/esaggsapi/0添加评论分享收藏感谢收起0添加评论分享收藏感谢收起数据在ElasticSearch,需要对数据进行统计分析,怎么做? - 知乎4被浏览1270分享邀请回答0添加评论分享收藏感谢收起您的 IP 地址/地理位置:49.76.95.204江苏&&无锡&&联通
当前位置: &
机器学习利用Elasticsearch进行更智能搜索 14:19:55&|&编辑:gxm&|&查看:&|&评论:
众所周知,机器学习正在引领许多行业的变革。对于曾疲于用人工调整搜索相关性来捕捉细微差别的搜索行业就更是如此。
众所周知,正在引领许多行业的变革。对于曾疲于用人工调整搜索相关性来捕捉细微差别的搜索行业就更是如此。人工调整已经实现了其能达到的最好效果,成熟的搜索公司不满足于此,试图建立更加智能和自动化的搜索系统。在本篇博文中,我想告诉你关于我们将机器学习集成到 Elasticsearch 中的排名系统中去,所做的一些工作。
因此,Elasticsearch 学习排序插件发布后我们非常激动。那么,学习排序是什么?用学习排序方法,一个团队就可以训练机器学习模型来判断用户行为的相关性。
在实现排名学习的时候,你需要:
通过分析来衡量用户对相关度的评价, 以构建出一个评价列表,将文档分为与查询精确相关、适度相关以及完全无关,这几个等级。
猜测那些特性可能对相关性的预测有所帮助, 比如指定域匹配的 TF*IDF , 新近程度, 搜索用户的个性特征等等。
对一个模型进行训练使其能够精确地将特性匹配到一个相关度等级上去。
将模型部署到你的搜索设施上去,利用它来在生产环境中对搜索结果进行排名。
不要被假象欺骗。上述这些步骤,其中的每一个底层都是复杂的、技术上实现起来比较困难的,以及非技术性的问题。
实施起来仍然不会有捷径可循。如我们在相关度搜索中所提过的, 对搜索结果的手工调整会遇到跟应用一个好的排名学习解决方案相比许多相同的挑战。
以后我们会在博文中就成熟的排名学习解决方案中关于基础设施、技术以及非技术性的挑战发表更多的意见。
在本篇博文中,我想告诉你关于我们将集成到 Elasticsearch 中的排名系统中去,所做的一些工作。客户在几乎每一次的相关咨询会议中都要问我们这项技术是否能帮助到他们。
然而,虽然在 Solr 中 Bloomberg 使其有了一个应用此技术的明确途径,但在 Elasticsearch 仍然没有。许多的客户想要的是 Elasticsearch 能满足更加与时俱进的可用性需求, 却发现在为他们的搜索技术栈选择该项技术方案时存在关键性的缺失。
诚然, Elasticsearch 的 DSL 查询可以利用强大的能力和复杂的架构来实现对结果的排名。一名熟练的相关领域的工程师可以利用查询 DSL 来计算出各种也许会标识出相关性的查询时间特性, 然后给出如下一些定量问题的回答:
标题中提到的搜索字条有多少?
文章、影片等等是多久之前发布的?
文档是如何同用户的浏览习惯相关联的?
该产品的价格相对于买房的预期是贵了还是便宜?
用户在搜索是使用的词条与文章主题之间的概念性相关度几何?
这些特性大部分都不是搜索引擎文档的静态属性。相反,它们是依赖于查询的,即计量用户、用户查询和某个文档的相关度。请关联搜索的读者知悉,这就是我们在书中提到的标记。
因此问题就变成了,如何将机器学习和 elasticsearch 提供的 Query DSL 查询相结合?这就是我们的插件要完成的工作:在用户向一个机器学习模型输入特征值的时候使用 Elasticsearch Query DSL 查询。
1.如何工作
这个插件集成了 RankLib 和 Elasticsearch。Ranklib 的输入是一个评分文件,它以易读格式输出一个内置的模型。
我们需要通过编程或者命令行训练这个模型。有了模型以后,Elasticsearch 插件会包含如下内容:
一个自定义的 Elasticsearch 脚本语音 ranklib,它可以接受 ranklib 的模型作为 Elasticsearch 脚本
一个自定义查询 ltr query,它的输入是包含了 Query DSL 查询(特征值)和模型名称(上一步那个)还有分数结果的列表。
鉴于排名学习模型的实现成本极高,你可能永远不会想要使用 ltr query,而是会像下面这样给前 N 个结果重新打分:
你可以到项目的 scripts 目录仔细研究这个功能完整的样例。这个例子封装严密,使用了 TMDB 的电影的手工评分。
我用 Elasticsearch 索引了 TMDB 来检索相应特征,然后用这些检索和特征的相应分扩大了评分文件,并在命令行训练了一个 Ranklib 模型。这个模型被我存储进 Elasticsearch,并用它执行了一条检索脚本。
别被这个简单的例子忽悠了。真实的排名学习方案是大量的工作的结果,包括研究用户、处理分析、数据工程和特征处理等。
我这么说不是要吓退你,而是你只要想想你的所得就明白你的付出是值得的。小型企业使用手工调整的 ROI 可能更好一些。
2.训练和加载排名学习模型
咱们就用我提供的这个手动创建的、迷你的排名列表来看一下我如何训练模型。
Ranklib 评分列表有十分严格的格式。第一列是文档评分,从 0 到 4。第二列是查询 id,比如 &qid:1.& 后面的列是检索文档对的特征值:左边的是基于 1 的特征索引,右边的是特征值。
下面是Ranklib README 中的数据:
注意一下注释(用井号开头的),是评分的文档标识。这个标识对于 Ranklib 没用,不过对应我们阅读很有用。后面我们会看到通过 Elasticsearch 检索也会用到这类标识符。
我们用一个最小版本的文件举例 (看 这里)。我们需要从文件的削减版开始,这个文件仅仅含有一级,查询 id 和文档 id 元组. 像这样:
如上所述,我们为分级的文件提供 Elasticsearch _id,作为每行的注释。
我们必须将每个查询 id (qid:1) 与实际的关键字查询 (&Rambo&) 相匹配,以便用关键字生成特征值。我们在例子代码的开头提供匹配关系:
# 在下面加入你的关键字, 特征脚本将会它们安置于查询模板
为使大家更好地了解,我将要把 ranklib&查询& (qid:1 等等) 作为关键字来区分 Elasticsearch Query DSL 查询 ,Elasticsearch Query DSL 查询是 Elasticsearch 用于生成特征值的明确的结构。
上述不是完整的 Ranklib 判断列表。当给定关键字查询文档时,它仅仅是相关性等级的极简案例。要成为完整的训练集,它需要包含上述值的特征,在每行第一个判断列表显示后包含 1:0 2:1 ... 等等。
为生成那些特征值,我们需要提出与电影相关的特征属性。正如我们刚才所述,有 Elasticsearch 查询。Elasticsearch 查询的分数将填充上述的判断列表。
上述例子中,我们用 jinja 模板与每个特征数字相对应。例如, 文件 1.json.jinja 是下面的 Query DSL 查询:
{ &query&: { &match&: { &title&: && } } }
换言之,对于我们的电影检索系统,当用户的关键字与标题字段匹配时,我们决定把特征 1 作为 TF*IDF 相关分数。文件 2.jinja.json , 遍及多个文本字段,做了更复杂的查询:
{ &query&: { &multi_match&: { &query&: &&, &type&: &cross_fields&, &fields&: [&overview&, &genres.name&, &title&, &tagline&, &belongs_to_collection.name&, &cast.name&, &directors.name&], &tie_breaker&: 1.0 } } }
学习排名的乐趣之一是假设特征的相关性。举例来说,在任意 Elasticsearch 查询中,你可以改变特征 1 和 2,你也可以通过增加额外的特征来实验。
特征太多就会出现问题,你需要充分的训练样本来覆盖所有合理的特征值。在后续文章中,我们将讨论更多关于训练与测试学习来排名模型。
通过精简版判断列表和 Query DSL 查询/特征 集这两个因素,我们要为 Ranklib 生成更多的判断列表,将 Ranklib 生成模型加载进 Elasticsearch。这意味着:
为特征和关键字/文档对获取相关分数。又称,向 Elasticsearch 发出查询,记录相关分数。
输出全量的判断文件,不仅关于级别以及关键字查询ids,而且有步骤 1 中的特征值:
运行 Ranklib 训练模型。
在查询时,加载模型至 Elasticsearch。
所有代码均在 train.py,我建议你进行拆分,在执行:
RankLib.jar 下载至 scripts 文件夹.
安装 Elasticsearch and Jinja2 Python 包(有一个 requirements.txt 文件)。
执行下面命令:
python train.py
这个脚本贯穿了上面提到的所有步骤,遍览代码:
首先,我们用文档加载精简的判断列表,关键字查询 id,级别元组,在文件开头指定的查询关键字:
judgements = judgmentsByQid(judgmentsFromFile(filename='sample_judgements.txt'))
然后,我们发出 Elasticsearch 查询,记录每一次判断的特征(在判断中增加通过率).
kwDocFeatures(es, index='tmdb', searchType='movie', judgements=judgements)
kwDocFeatures 功能遍历 1.json.jinja 到 N.json.jinja(特征/查询),批量 Elasticsearch 查询获取相关分数,为每一个关键字/文档元组使用 Elasticsearch 批量查询 (_msearch) API。代码在这里可以看。
一旦我们有全量的特征,我们就在新文件输出全量的训练集(判断附加特征)(sample_judgements_wfeatures.txt):
buildFeaturesJudgmentsFile(judgements, filename='sample_judgements_wfeatures.txt')
输出与 Ranklib 判断列表相符:
3 qid:1 1:9.:25.821222 # 1370 3 qid:1 1:6.:23.463709 # 1369
特征 1 是 &Rambo& 的 TF*IDF 分数查询(1.json.jinja),特征 2 是更复杂的 TF*IDF 分数查询(2.json.jinja)
接下来,我们训练!以下行使用保存的文件作为判断数据,通过命令行来执行 Ranklib.jar。
trainModel(judgmentsWithFeaturesFile='sample_judgements_wfeatures.txt', modelOutput='model.txt')
正如你所看到的,这里只是简单地执行 java -jar Ranklib.jar 来训练 LambdaMART 模型:
def trainModel(judgmentsWithFeaturesFile, modelOutput): # java -jar RankLib-2.6.jar -ranker 6 -train sample_judgements_wfeatures.txt -save model.txt cmd = &java -jar RankLib-2.6.jar -ranker 6 -train %s -save %s& % (judgmentsWithFeaturesFile, modelOutput) print(&Running %s& % cmd) os.system(cmd)
我们之后将该模型保存到 Elasticsearch,使用下面简单的 Elasticsearch 命令:
saveModel(es, scriptName='test', modelFname='model.txt')
这里 saveModel 仅仅是读取文件内容,并将其作为 ranklib 脚本以 POST 方式存储到 Elasticsearch 中。
3.使用学习排序模型进行搜索
一旦你完成了训练,你就可以进行搜索了!在 search.py 中有一个简单的查询例子。 你可以运行 python search.py rambo,它将使用训练好的模型搜索&rambo&,执行重新评分查询:
注意,我们只在这里排序前20个结果。 我们直接使用学习排序查询。 事实上,直接运行模型就工作得很好。
虽然它需要几百毫秒来搜索整个集合。 对于更大的集合,它就不能工作了。 一般来说,由于学习排序模型的性能成本,最好重新排序前 N 个结果。
这个例子只是为了抛砖引玉。 你需要根据实际问题的不同选择功能,如特征,记录特征的方式,训练模型的方式以及实施基准排名功能等。 这些在我们写的相关搜索中仍然适用。
作者:OSC-协作翻译来源:开源中国|
相关阅读:
搜索"raincent"或扫描下面的二维码用ElasticSearch搭建自己的搜索和分析引擎
09:36:28 来源:
优就业:互联网产品中的检索功能随处可见。当你的项目规模是百度大搜|商搜或者微信公众号搜索这种体量的时候,自己开发一个搜索引擎,加入各种定制的需求和优化,是非常自然的事情。但如果只是普通的中小型项目甚至创业团队|创业项目,直接拿轮子则是更合理的选择。 ElasticSearch就是这样一个搜索引擎的轮子。更重要的是,除去常规的全文检索功能之外,它还具有基础的统计分析功能(最常见的就是聚合),这也让他变得更加强大和实用。 还在用数据库的like来实现产品的全文检索吗?抛弃她,用ElasticSearch吧~
ElasticSearch(下简称ES)是基于Lucene的一个开源搜索引擎产品。Lucene是java编写的一套开源文档检索的基础库,包括词、文档、域、倒排索引、段、相关性得分等基本功能,而ES则是使用了这些库,搭建的一个可以直接拿来使用的搜索引擎产品。直观地理解,Lucene提供汽车零部件,而ES直接卖车。
说起ES的诞生,也是个很有意思的故事。ES的作者Shay Banon&&&几年前他还是一个待业工程师,跟随自己的新婚妻子来到伦敦。妻子想在伦敦学习做一名厨师,而自己则想为妻子开发一个方便搜索菜谱的应用,所以才接触到Lucene。直接使用Lucene构建搜索有很多问题,包含大量重复性的工作,所以Shay便在Lucene的基础上不断地进行抽象,让Java程序嵌入搜索变得更容易,经过一段时间的打磨便诞生了他的第一个开源作品Compass,中文即'指南针'的意思。之后,Shay找到了一份面对高性能分布式开发环境的新工作,在工作中他渐渐发现越来越需要一个易用的、高性能、实时、分布式搜索服务,于是他决定重写Compass,将它从一个库打造成了一个独立的server,并将其改名为Elasticsearch。&
引自(q.com/cn/news/2014/12/elasticsearch-birth-development)。
可见鼓捣起来的程序员是多么有爱,虽然据说Shay Banon承诺给妻子的菜谱搜索还没问世......
本文大概地介绍了ES的原理,以及Wetest在使用ES中的一些经验总结。因为ES本身涉及的功能和知识点非常广泛,所以这里重点挑出了实际项目中可能会用到,也可能会踩坑的一些关键点进行了阐述。
集群(Cluster):ES是一个分布式的搜索引擎,一般由多台物理机组成。这些物理机,通过配置一个相同的cluster name,互相发现,把自己组织成一个集群。
节点(Node):同一个集群中的一个 Elasticearch主机。
主分片(Primary shard):索引(下文介绍)的一个物理子集。同一个索引在物理上可以切多个分片,分布到不同的节点上。分片的实现是Lucene 中的索引。
注意:ES中一个索引的分片个数是建立索引时就要指定的,建立后不可再改变。所以开始建一个索引时,就要预计数据规模,将分片的个数分配在一个合理的范围。
副本分片(Replica shard):每个主分片可以有一个或者多个副本,个数是用户自己配置的。ES会尽量将同一索引的不同分片分布到不同的节点上,提高容错性。对一个索引,只要不是所有shards所在的机器都挂了,就还能用。主、副本、节点的概念如下图:
索引(Index):逻辑概念,一个可检索的文档对象的集合。类似与DB中的database概念。同一个集群中可建立多个索引。比如,生产环境常见的一种方法,对每个月产生的数据建索引,以保证单个索引的量级可控。索引-&类型-&文档,ES中的文档以这样的逻辑关系组织了起来。
类型(Type):索引的下一级概念,大概相当于数据库中的table。同一个索引里可以包含多个 Type。 个人感觉在实际使用中type这一级常常用的不多,直接就在一个索引中建一个type,在这个type下去建立文档集合和进行搜索了。
文档(Document):即搜索引擎中的文档概念,也是ES中一个可以被检索的基本单位,相当于数据库中的row,一条记录。
字段(Field):相当于数据库中的column。ES中,每个文档,其实是以json形式存储的。而一个文档可以被视为多个字段的集合。比如一篇文章,可能包括了主题、摘要、正文、作者、时间等信息,每个信息都是一个字段,最后被整合成一个json串,落地到磁盘。
映射(Mapping):相当于数据库中的schema,用来约束字段的类型,不过 Elasticsearch 的 mapping 可以不显示地指定、自动根据文档数据创建。
Elasticsearch很友好地提供了RestFul的API,可以通过HTTP请求直接完成所有操作。比如下面官方的一个例子,往索引twitter添加文档,type是tweet,文档的id是1:
相应地,根据user字段检索文档:
关键配置项
1、索引的shards个数:
shards的个数,最好是和节点数相关的。理论上对同一个索引,单机上的shards个数最好不要超过两个,这样每个查询尽可能并行。但因为ES中shards的个数是确定了就没办法再调整的,所以如果考虑到数据会高速增长,一开始分配多些也可以。另一个常见思路是按时间纬度(如月)去定义ES索引&&因为可以动态调整新加的索引的shards个数。其他的一些情况,比如下面举到的Wetest聚合的例子,因为需要数据尽量地按照渠道切分开,所以定义了很多个shards(200个),但太多的shards通常是不推荐的,ES管理起来也有开销。
2、heap内存:
官方建议是可用内存的一半,是通过启动ES的环境中,定义环境变量的方式完成的。如export ES_HEAP_SIZE=10g
3、cluster.name:
集群的逻辑名称。只有cluster name相同的机器,才会在逻辑上组成一个集群。比如,内网中有5台ES机器的实例,是可以构成几个互不干扰的ES集群的。
4、discovery.zen.minimum_master_nodes:
这个是用于集群的分布式决策的最少master机器个数。和常见的分布式协调算法一样,为了避免脑裂现象,建议超过一半的机器,n/2+1
5、discovery.zen.ping.unicast.hosts:
ES集群的机器列表。注意ES单点不用配置集群中的所有机器列表,像一个连通图一样,只要每台机器配置了其他机器,而这些配置又是互相可以连接的,那ES最终就会发现所有机器,构成集群。如['111.111.111.0','111.111.111.1','111.111.111.2']
mapping类似于数据库里的表结构,定义个mapping就意味着创建了一个索引。与数据库不同的是,一个索引并不需要显示地建立mapping,比如,上面那个在twitter索引插入文档数据的例子,如果执行的时候还没有定义索引,ES便会根据文档的字段和内容,自动创建索引和mapping。然而,这样创建的索引字段,往往可能不是我们所需要的。所以,还是自己预先通过手动定义mapping来创建索引比较好。下面是创建mapping的例子,这个例子在my_index这个目录下,为user、blogpost这些type创建了mapping。其中properties下面是各种字段的定义,包括了string、数值、日期等类型的定义。
如图中的红框部分,这个例子中有两个需要注意的地方:
1、user_id是string类型的,但它的index被定义为了&not_analzyed&,这个需要搞清其中的意义:通常,搜索引擎中全文检索的功能简单说是这样实现的:对原始文档进行分词后用这些词去建立倒排索引,在线上检索时,再将用户的查询词进行分词,用分词结果去拉取多个倒排索引的拉链结果、归并、相关性排序等,得到最终结果。但是,对于有些string类型的字段,其实并不想建倒排,就只想精确匹配,比如用户的名字,只想查到name字段精确为&张三&的人,而不是分词后得到的&张四&和&李三&两个人,这个时候,就需要定义index类型字段。这个字段有no、analyzed、not_analyzed三种类型,no是压根儿不给这字段建索引,analyzed是分析和按全文检索的方式建,not_analyzed是完全匹配的关键词查询方式。
2、date类型,创建mapping时需要通过&format&指定录入的多种可能时间格式。这样创建文档的时候,ES会根据输入文档的字段自动去确定是哪一种。不过直观地想象下,在创建文档时,指定明确的时间格式,省去ES动态判断的开销,应该会提升些微小的性能。此外,要注意,epoch_second(秒单位时间戳)和epoch_millis(毫秒单位)尽量不要混用,如果非要混用也要在插入的时候明确指明是哪个。曾经踩过坑,插入epoch_second的是秒级时间戳,但ES优先认为是毫秒,导致时间被缩小1000倍,最近的时间变成了1970年当年的某个时间。
下图列出了ES当前版本中可以进行mapping的数据类型、内置的字段、mapping操作可以携带的参数。因为篇幅原因这里就不详细解释了:
这里要详细介绍的,是上图中红框标出的,我们创建mapping时实际用到的比较关键的两个内置类型,和两个mapping参数。这几个都会直接影响最后索引访问的性能:
1)_source:es会把所有字段拼成一个原始的json落入磁盘,所以这个可以理解为全量原始数据,他不能用来索引,却可以在需要的时候返回。注意尽量不要禁用,比如禁用后,用script去update就不支持了。
2)_all:一个&伪&字段,用来实现模糊的全文索引。可以这样理解:在建索引的时候,把所有字段拼成一个字符串,然后对这个&大&字段进行切词,建倒排,然后这个字段就被丢弃了,没有真正落入磁盘。当全文检索时,如果没有指明查询的域,比如标题、正文(这种是很常见的),就从这个大的倒排中拉取文档拉链。可以想象,一些标记或值类型的字段,如日期、得分,这种在全文检索时是没意义的,就可以不包含在_all内,而文本域,如title、doc,就包含在_all之中。这些都是在建mapping时可以、而且最好指定的。
3)doc_values:doc_values和下面的field_data都是在聚合(后面会介绍)、排序这些统计时用的参数,默认都是开启的。排序、聚合,这种在文档全局进行的工作,用倒排索引肯定不合适。所以,对not_analyzed(即不建倒排)的字段,doc_values用一种列模式的方式(可以参考hbase)来存储文档的正排,方便在文档全局做统计。doc_values是存储在磁盘的,如果你明确有些字段只是展示,不用于统计的话,可以把这个禁用掉。Doc_values一定不会对analyzed域建索引(都切词了,想想也不合适,怎么建列索引嘛),而是用下面的field data。
4)field_data:对analyzed的文本域,比如正文,其实也会有统计的需求(比如ES也支持按一些关键词对文档进行聚合统计,但这种任务常用的方法是通过离线工具,如hadoop或者单机的分析,做好了后推送到在线索引,直接在ES去算其实感觉有些奇怪)。虽然并不适合在搜索引擎中做,但你真的做了,es也会把这个数据动态地load内存的一个field data中进行运算。所以,想想就知道,这是个非常耗内存的操作,很可能把jvm heap吃完了!!es默认是只打开,但不load,只是在你需要进行analyzed域的排序和聚合的时候,才去动态load这个内存(lazy的方式)。所以,尽量不要在查询的时候去打开这个潘多拉魔盒,或者干脆就把这个选项关掉吧。
谁说搜索引擎只能用来搜索?ES不仅能搜索,还能在搜索的结果集合上直接进行统计,很强大吧。ES目前稳定的非实验阶段聚合主要分两种:Metrics Aggregation(指标聚合)和Bucket Aggregation(桶聚合)。
指标聚合主要指常规的集合数学统计类运算,如官方guide的这个例子:找到交易的所有红色的车,然后求它们的平均价格:
结果大概是这样的:
神奇吧~指标运算还包括其他,如最大、最小、求和、个数、地理坐标运算等。然而我们今天要进行实例讲解的则主要是Bucket Aggregation,桶聚合。桶聚合是指把文档,按照某个给定字段分成不同的组,然后在组内进行进一步聚合运算,并返回桶级的结果。比较直观的理解,如:直方图、分时间段统计等等。如下面这个例子,是桶聚合中的term聚合,即按照color这个字段,精确匹配后进行分桶,然后桶内还进一步嵌套了平均价格聚合、和按制造商进一步的分桶聚合。
统计的结果类似下面这样,红色的车共有4辆,平均价格是32500,并且又包含了3辆本田和1辆宝马:
上面是简单的例子。在我们的WeTest舆情中,有论坛热帖这样一个功能,即,实时统计某个数据源中(如百度贴吧),某个论坛里(如王者荣耀吧),一段时间内(如3个月),回复数最多的TopN个帖子。
这个功能现在在线上的实现方法就不详细介绍了,大致是从数据库和Hbase中扫描对应的数据,维持一个堆,获取出TOP N的思路。一方面是稍微有些耗时,另一方面是请求量很大时可能对DB和Hbase的访问带来压力,所以也想找一种备选的方案,我们想到了用ES。
为了用ES的桶聚合,我们首先设计如何存储文档(即所有用户评论)的方案。由于数据量非常大(十亿级),所以我们首先想到了把文档按时间分成不同的索引(如按月),然后在指定月份(如3个月)的索引上,聚合出评论最多的Top帖子。然而这样是有问题的:当在多个ES索引上聚合时,ES不会把所有索引的结果放在一起聚合TopN,而是单独在每个索引求得TopN后,再放在一起聚合。这是个使用时要注意的小坑。这样导致的结果是,直接在多个索引上聚合出的TopN,并不是真正的TopN(比如3个月中,每个月都是不是Top 1,但三个月加起来就是Top了 1。局部最优不等于全局最优)。
所以,从时间上切分,这条路基本被堵死了。那只能从空间上切分了(您问能不能不切分?十亿级的数据量,上百个GB,不切分的话,乖乖,每次都要从这几百GB的文件里找东西,想想也知道有多慢了...)。从空间切分,同样需要考虑两个问题:1)如何将数据hash到shards。2)切分多少个shards。对于第一个问题,因为我们的聚合统计是在每个渠道(可以理解为论坛)下的,不会跨渠道,所以,按照渠道ID进行shards分配,把相同论坛的数据hash到一个shard即可。这样,每次请求某个渠道的聚合结果,把请求按渠道ID routing到对应的shard去运算。对于第二个问题,要看具体的规模了。我们的数据量有上百G,数据源上千个,所以我们希望每个shard上的内容尽量少,保证在单个shard上聚合的时候会更快,当然shards个数又不能太多,否则会给ES引入非常大的管理开销。综合下来,我们选择的shards个数是200个。
遗憾的是,ES只能根据你指定的key(论坛ID)去做hash后进行路由,这就导致了不同的shards上数据不是完全平均的,最多的能超过10GB,最少的只有几十MB。如果哪一天,ES如果开放自定义routing规则或者对shards数据进行均衡的方法,那就好了。
ES经常为人诟病的一个地方是建索引比较慢,10亿数据的索引构建时间要花几天。这也容易理解,天下没有免费的午餐,读写的性能往往是互斥的,快速读取和检索意味着大量索引和辅助数据的预先建立,那写入时势必会慢。如何取舍,需要看实际的业务场景而定了。下面就是建好索引后,去聚合某论坛内指定时间段内Top帖子的接口调用方式。
然后,我们按连续统计最热的TopN(N为不同的个数)个渠道内的Top30热帖结果的方式分别对ES和线上已有的服务进行了测试:
上面的五个结果图直观地反应了用现在Wetest舆情线上的常规统计方式和ES聚合统计的方式获取结果的耗时。
从结果中,我们大概推断出了ES统计聚合运算的做法:先把所有符合过滤条件的数据全部检索出来,然后在内存中进行排序和聚合运算。也就是说,符合条件的数据量级越大,聚合运算越慢。本着这个原则,结果图也就比较好理解了:
1)在连续对最热的Top1000个渠道去进行热帖聚合时,ES的表现大部分都优于现有实现。这是因为Top1000的渠道中,大部分渠道被分在了非常小的shards上,有的只有几MB,数据量很小,在这样的shards中聚合,是很快的。
2)时间纬度上,统计3个月的数据,ES大部分情况下都比现有方法慢,而1个月或1天的情况下,ES都要快。这是因为3个月的条件下,符合条件的数据量级增大(最大的一个话题下有3万跟帖),ES的运算效率下降比较厉害。
3)从Top1000到Top10,ES的总时间逐渐变差于现有方法。这是因为,空间纬度上,Top10渠道符合条件的数据量级非常大,所以ES的运算效率下降比较厉害。
做了这个实验后,ES在WeTest头部数据源上的聚合速度并不比现在快,但在中部和长尾上的效果更优,这说明ES的聚合受候选集数据量的影响非常大,所以是否切换这种方式也还没最终决定。不过,这个实验证明了ES聚合的强大能力,至少,不用自己写什么代码,只通过接口调用就能把这样海量数据的统计运算完成了,还是很方便的一件事情,同时性能也不错。如果自行实现的统计运算中会增大DB的压力,那么通过ES聚合分离这部分请求,也是一个非常好的选择。
免责声明:本文来源于,由网友提供或网络搜集,仅供个人研究、交流学习使用,不涉及商业盈利目的。如有版权问题,请联系本站管理员予以更改或删除。会定期发布程序开发相关趋势文章,包括&、&、&、&、&、&、&、&&等领域,敬请关注!
微信二维码
微博二维码
免责声明:本文来源于网络,由网友提供或网络搜集,仅供个人交流学习参考使用,不涉及商业盈利目的。如有版权问题,请联系本站管理员予以更改或删除。谢谢合作!
热门标签:
QQ一键加群
微信扫一扫
400-650-7353}

我要回帖

更多关于 数据统计分析模板 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信