轻量级OLAP(二):Hive + Elasticsearch
1. 引言
在做OLAP数据分析时,常常会遇到过滤分析需求,比如:除去只有性别、常驻地标签的用户,计算广告媒体上的覆盖UV。OLAP解决方案Kylin不支持复杂数据类型(array、struct、map),要求数据输入Schema必须是平铺的,但是平铺后丢失了用户的聚合标签信息,而没有办法判断某一个用户是否只有性别、常驻地标签。显然,我们需要一种支持复杂数据类型的OLAP数据库;底层为Lucene的Elasticsearch正在向OLAP融合,腾讯内部已经用基于Lucene的分析数据库Hermes来做多维数据分析。
Elasticsearch(ES)在设计之初是用来做全文检索的搜索引擎,但随着倒排索引所表现出来优秀的查询性能,有越来越多人拿它做分析数据库使。可将ES视作文档型NoSQL数据库,一般情况下将具有相同schema的文档(document)归属于一个type,所有的文档存储于某一个index;ES与RDBMS的概念对比如下:
Relational DB ⇒ Databases ⇒ Tables ⇒ Rows ⇒ Columns
Elasticsearch ⇒ Indices ⇒ Types ⇒ Documents ⇒ Fields
2. 写数据
广告日志与标签数据均落在Hive表,并且ES官方提供与Hive的集成。因此,我们首选用Hive向ES写数据。首先,采用ES做OLAP分析引擎,创建表如下:
add jar /path/elasticsearch-hadoop-2.3.1.jar;
create external table ad_tag (
dvc string,
medias array < string >,
c1_arr array < string >,
week_time string
) stored by 'org.elasticsearch.hadoop.hive.EsStorageHandler' tblproperties(
'es.nodes' = '<ip1>:9200,<ip2>:9200',
'es.resource' = 'ad-{week_time}/tag',
'es.mapping.exclude' = 'week_time'
);
在设计Hive表结构时,ES的计算UV的distinct count(cardinality
)存在着计算误差;因此,我们按dvc对其他字段做了聚合,UV的计算转换成了ES doc命中数。其中,es.nodes
表示ES的节点,只需配置一个节点即可;es.resource
对应于ES的Index/Type;es.mapping.exclude
在写ES时不会被索引的字段。因我们只有写操作而没有通过Hive查询ES数据,因此并没有设置es.query
。Hive向ES写数据如下:
set hive.map.aggr = false;
insert overwrite table ad_tag
select
media,
a.dvc as dvc,
case when c1_arr is null then array('empty') else c1_arr end as c1_arr,
'2016-10-08' as week_time
from
(
select
dvc,
app_name as media
from
ad_log
where
is_exposure = '1'
and day_time between date_sub('2016-10-08', 6)
and '2016-10-08'
group by
dvc,
app_name
) a
left outer join (
select
dvc,
collect_set(c1) as c1_arr
from
tag lateral view inline(tag) in_tb
where
day_time = '2016-10-08'
group by
dvc
) b on a.dvc = b.dvc;
在写ES时,在构建索引时不需要分词,通过PUT index template方式实现之:
{
"template": "ad*",
"mappings": {
"_default_": {
"dynamic_templates": [
{
"string_template": {
"mapping": {
"include_in_all": false,
"index": "not_analyzed",
"type": "string",
"index_options": "docs"
},
"match": "*"
}
}
]
}
}
}
3. 多维分析
ES官方的查询语言是DSL,主要分为两类:
- Query,相当于SQL中的where部分,可套用filter、match等;
- Aggregation,相当于SQL中的group by部分,在aggs内部也可以套用filter。
DSL可以嵌套,表达异常复杂的查询操作;但是,若以字符串拼接的方式实现DSL,则显得可维护性太差。因此,官方提供了elasticsearch-dsl-py,可以将DSL等同于一段Python代码。我们的多维分析器便是基于此实现的(Python 3.5 + elasticsearch_dsl 2.1.0)
整体上曝光UV、有标签的UV、除去常用标签UV,以及每一个媒体上曝光UV、有标签的UV、除去常用标签UV的分析(相当于group by media with cube):
client = Elasticsearch(['<host1>'], port=20009, timeout=50)
def per_media(index_name):
"""count(distinct dvc) group by media with cube"""
ms = MultiSearch(using=client, index=index_name)
all_doc = Search()
all_doc.aggs.bucket('per_media', 'terms', field='medias', size=1000)
tagged = Search().query('filtered', filter=~Q('term', c1_arr='empty'))
tagged.aggs.bucket('per_media', 'terms', field='medias', size=1000)
useful = Search().query('filtered', filter=~Q('term', c1_arr='empty') & Q('script',
script="""['常驻地', '性别'].intersect(doc['c1_arr'].values).size() < doc['c1_arr'].values.size()"""))
useful.aggs.bucket('per_media', 'terms', field='medias', size=1000)
ms = ms.add(all_doc)
ms = ms.add(tagged)
ms = ms.add(useful)
responses = ms.execute()
result_list = []
result_dict = defaultdict(lambda: [])
for resp in responses: # get per media uv(all, tagged, useful_tagged)
print("Query %d: %r." % (responses.index(resp), resp.search.to_dict()))
result_list.append(resp.hits.total)
for buck in resp.aggregations['per_media']['buckets']:
result_dict[buck['key']].append(buck['doc_count'])
for k, v in result_dict.items(): # fill up default value 0
if len(v) < 3:
result_dict[k] = v + [0] * (3 - len(v))
return result_list, result_dict
媒体与标签组合维度下的UV统计:
def per_media_c1(index_name):
"""return {(media, c1) -> tagged_uv}"""
s = Search(using=client, index=index_name)
tagged = s.query('filtered', filter=~Q('term', c1_arr='empty'))
tagged.aggs.bucket('per_media', 'terms', field='medias', size=1000) \
.bucket('per_c1', 'terms', field='c1_arr', size=100)
result = {}
response = tagged.execute()
for buck in response.aggregations['per_media']['buckets']:
key = buck['key']
for b in buck['per_c1']['buckets']:
result[(key, b['key'])] = b['doc_count']
return result
轻量级OLAP(二):Hive + Elasticsearch的更多相关文章
- 二 Hive分桶
二.Hive分桶 1.创建分桶表 create table t_buck (id string ,name string) clustered by (id) //根据id分桶 sorted by ( ...
- Elasticsearch入门教程(二):Elasticsearch核心概念
原文:Elasticsearch入门教程(二):Elasticsearch核心概念 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:ht ...
- HA分布式集群二hive配置
一,概念 hive:是一种数据仓库,数据储存在:hdfs上,hsql是由替换简单的map-reduce,hive通过mysql来记录映射数据 二,安装 1,mysql安装: 1,检测是否有mariad ...
- ELK学习记录二 :elasticsearch、logstash及kibana的安装与配置
注意事项: 1.ELK版本要求5.X以上,本人使用版本:elasticsearch-6.0.0.kibana-6.0.0-linux-x86_64.logstash-6.0.0.tar 2.Elast ...
- DDD实战进阶第一波(三):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架二)
了解了DDD的好处与基本的核心组件后,我们先不急着进入支持DDD思想的轻量级框架开发,也不急于直销系统需求分析和具体代码实现,我们还少一块, 那就是经典DDD的架构,只有了解了经典DDD的架构,你才能 ...
- ES之二:Elasticsearch原理
Elasticsearch是最近两年异军突起的一个兼有搜索引擎和NoSQL数据库功能的开源系统,基于Java/Lucene构建.最近研究了一下,感觉 Elasticsearch 的架构以及其开源的生态 ...
- 〈二〉ElasticSearch的认识:索引、类型、文档
目录 上节回顾 本节前言 索引index 创建索引 查看索引 查看单个索引 查看所有索引 删除索引 修改索引 修改副本分片数量 关闭索引 索引别名 增加索引别名: 查看索引别名: 删除索引别名: 补充 ...
- 轻量级OLAP(一):Cube计算
有一个数据多维分析的任务: 日志的周UV: APP的收集量及标注量,TOP 20 APP(周UV),TOP 20 APP标注分类(周UV): 手机机型的收集量及标注量,TOP 20 机型(周UV),T ...
- ELK 之二:ElasticSearch 和Logstash高级使用
一:文档 官方文档地址:1.x版本和2.x版本 https://www.elastic.co/guide/en/elasticsearch/guide/index.html 硬件要求: 1.内存,官方 ...
随机推荐
- 玩转spring boot——结合jQuery和AngularJs
在上篇的基础上 准备工作: 修改pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q ...
- Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级
Linux平台 Oracle 10gR2(10.2.0.5)RAC安装 Part2:clusterware安装和升级 环境:OEL 5.7 + Oracle 10.2.0.5 RAC 3.安装Clus ...
- Python(九) Python 操作 MySQL 之 pysql 与 SQLAchemy
本文针对 Python 操作 MySQL 主要使用的两种方式讲解: 原生模块 pymsql ORM框架 SQLAchemy 本章内容: pymsql 执行 sql 增\删\改\查 语句 pymsql ...
- 编写高质量代码:改善Java程序的151个建议(第8章:异常___建议114~117)
建议114:不要在构造函数中抛出异常 Java异常的机制有三种: Error类及其子类表示的是错误,它是不需要程序员处理也不能处理的异常,比如VirtualMachineError虚拟机错误,Thre ...
- win10上部署Hadoop-2.7.3——非Cygwin、非虚拟机
开始接触Hadoop,听人说一般都是在Lunix下部署Hadoop,但是本人Lunix不是很了解,所以Google以下如何在Win10下安装Hadoop(之后再在Lunix下弄),找到不少文章,以下是 ...
- 【转】组件化的Web王国
本文由 埃姆杰 翻译.未经许可,禁止转载!英文出处:Future Insights. 内容提要 使用许多独立组件构建应用程序的想法并不新鲜.Web Component的出现,是重新回顾基于组件的应用程 ...
- Struts2数据校验
Struts2数据校验 1.常见数据校验方法 表单数据的校验方式: 表单中的数据必须被效验以后才能够被使用,常用的效验方式分为两种: 前台校验:也称之为客户端效验,主要是通过JS编程的方式进行表单数据 ...
- 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)
目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...
- Ubuntu(Linux) + mono + jexus +asp.net MVC3 部署
感谢 张善友 的建议,我把 微信订餐 由nginx 改成 jexus,目前运行状况来说,确实稳定了很多,再次感谢. 部署步骤参考 jexus官网:http://www.jexus.org/ htt ...
- 微软.Net 社区虚拟大会 -- 首日重点(dotnetConf 2016)
6月7日--9日,为期三天的微软.NET社区虚拟大会正式在 Channel9 上召开. 在 Scott Hunter, Miguel de Icaza (Xamarin CTO) , ScottHan ...