尚硅谷数据仓库 用户行为分析

数据仓库的输入数据通常包括:业务数据、用户行为数据和爬虫数据等

业务数据:就是各行业在处理事务过程中产生的数据。比如用户在电商网站中登录、下单、支付等过程中,需要和网站后台数据库进行增删改查交互,产生的数据就是业务数据。业务数据通常存储在MySQL、Oracle等数据库中。    

用户行为数据:用户在使用产品过程中,通过埋点收集与客户端产品交互过程中产生的数据,并发往日志服务器进行保存。比如页面浏览、点击、停留、评论、点赞、收藏等。用户行为数据通常存储在日志文件中

爬虫数据:通常事通过技术手段获取其他公司网站的数据。不建议同学们这样去做。

项目需求
1.用户行为数据采集平台搭建
2.业务数据采集搭建
3.数据仓库维度建模
4.分析、设备、会员、商品、地区、活动等电商核心主题,统计的报表指标近100个
5.采用即席查询工具,随时进行指标分析
6.采取集群性能进行监控、发生异常需要报警
7.元数据管理
8.质量监控
9.权限管理

用户行为数据
我们要收集和分析的数据主要包括页面数据、事件数据、曝光数据、启动数据和错误数据。
页面:页面数据主要记录一个页面的用户访问情况,包括访问时间、停留时间、页面路径等信息。
事件:事件数据主要记录应用内一个具体操作行为,包括操作类型、操作对象、操作对象描述等信息。
曝光:曝光数据主要记录页面所曝光的内容,包括曝光对象,曝光类型等信息。
启动:启动数据记录应用的启动信息。
错误:错误数据记录应用使用过程中的错误信息,包括错误编号及错误信息。

我们的日志结构大致可分为两类,一是普通页面埋点日志,二是启动日志。
普通页面每条日志包含了,当前页面的页面信息,所有事件(动作)、所有曝光信息以及错误信息。除此之外,还包含了一系列公共信息,包括设备信息,地理位置,应用信息等,即下边的common字段。
启动日志结构相对简单,主要包含公共信息,启动信息和错误信息。

开启数据均衡命令
节点间数据均衡
start-balancer.sh -threshold 10
对于参数10,代表的是集群中各个节点的磁盘空间利用率相差不超过10%,可根据实际情况进行调整。
注意:于HDFS需要启动单独的Rebalance Server来执行Rebalance操作,所以尽量不要在NameNode上执行start-balancer.sh,而是找一台比较空闲的机器。
磁盘间数据均衡
hdfs diskbalancer -plan hadoop103
hdfs diskbalancer -execute hadoop103.plan.json
hdfs diskbalancer -query hadoop103
hdfs diskbalancer -cancel hadoop103.plan.json

支持lzo压缩模式
lzo创建索引
LZO压缩文件的可切片特性依赖于其索引,故我们需要手动为LZO压缩文件创建索引。若无索引,则LZO文件的切片只有一个。

flume时间拦截器
由于Flume默认会用Linux系统时间,作为输出到HDFS路径的时间。如果数据是23:59分产生的。Flume消费Kafka里面的数据时,有可能已经是第二天了,那么这部门数据会被发往第二天的HDFS路径。我们希望的是根据日志里面的实际时间,发往HDFS的路径,所以下面拦截器作用是获取日志中的实际时间。
解决的思路:拦截json日志,通过fastjson框架解析json,获取实际时间ts。将获取的ts时间写入拦截器header头,header的key必须是timestamp,因为Flume框架会根据这个key的值识别为时间,写入到HDFS。


业务数据
以下为本电商数仓系统涉及到的业务数据表结构关系。这34个表以订单表、用户表、SKU商品表、活动表和优惠券表为中心,延伸出了优惠券领用表、支付流水表、活动订单表、订单详情表、订单状态表、商品评论表、编码字典表退单表、SPU商品表等,用户表提供用户的详细信息,支付流水表提供该订单的支付详情,订单详情表提供订单的商品数量等情况,商品表给订单详情表提供商品的详细信息。本次讲解以此34个表为例,实际项目中,业务数据库中表格远远不止这些。

同步策略

 某些特殊的表,可不必遵循上述同步策略。例如某些不会发生变化的表(地区表,省份表,民族表)可以只存一份固定值。

mysql to hdfs

Hive中的Null在底层是以“\N”来存储,而MySQL中的Null在底层就是Null,为了保证数据两端的一致性。在导出数据时采用--input-null-string和--input-null-non-string两个参数。导入数据时采用--null-string和--null-non-string。

关系建模和维度建模是两种数据仓库的建模技术。

关系建模将复杂的数据抽象为两个概念——实体和关系,并使用规范化的方式表示出来。关系模型如图所示从图中可以看出,较为松散、零碎,物理表数量多

关系模型严格遵循第三范式(3NF)数据冗余程度低,数据的一致性容易得到保证。由于数据分布于众多的表中,查询会相对复杂,在大数据的场景下,查询效率相对较低。

维度模型如图所示,从图中可以看出,模型相对清晰、简洁。

维度模型以数据分析作为出发点,不遵循三范式,故数据存在一定的冗余。维度模型面向业务,将业务用事实表和维度表呈现出来。表结构简单,故查询简单,查询效率较高。

 A完全依赖B 反过来 即 B决定A

维度表:一般是对事实的描述信息。每一张维表对应现实世界中的一个对象或者概念。    例如:用户、商品、日期、地区等。

维表的特征:

  • 维表的范围很宽(具有多个属性、列比较多)
  • 跟事实表相比,行数相对较小:通常< 10万条
  • 内容相对固定:编码表

事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等)。“事实”这个术语表示的是业务事件的度量值(可统计次数、个数、金额等),例如,2020年5月21日,宋宋老师在京东花了250块钱买了一瓶海狗人参丸。维度表:时间、用户、商品、商家。事实表:250块钱、一瓶

每一个事实表的行包括:具有可加性的数值型的度量值、与维表相连接的外键,通常具有两个和两个以上的外键。

事实表的特征:

  • 非常的大
  • 内容相对的窄:列数较少(主要是外键id和度量值)
  • 经常发生变化,每天会新增加很多。

1)事务型事实表

每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。

2)周期型快照事实表

周期型快照事实表中不会保留所有数据只保留固定时间间隔的数据,例如每天或者每月的销售额,或每月的账户余额等。

例如购物车,有加减商品,随时都有可能变化,但是我们更关心每天结束时这里面有多少商品,方便我们后期统计分析。

3)累积型快照事实表

累计快照事实表用于跟踪业务事实的变化。例如,数据仓库中可能需要累积或者存储订单从下订单开始,到订单商品被打包、运输、和签收的各个业务阶段的时间点数据来跟踪订单声明周期的进展情况。当这个业务过程进行时,事实表的记录也要不断更新。

在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型。

数仓分层

ods层(原始数据层):不需要建模,存放原始数据

针对HDFS上的用户行为数据和业务数据,我们如何规划处理?

(1)保持数据原貌不做任何修改,起到备份数据的作用。

(2)数据采用压缩,减少磁盘存储空间(例如:原始数据100G,可以压缩到10G左右)

(3)创建分区表,防止后续的全表扫描

dim和dwd层 数据明细层和维度层

DIM层DWD层需构建维度模型,一般采用星型模型,呈现的状态一般为星座模型。

维度建模一般按照以下四个步骤:

选择业务过程→声明粒度→确认维度→确认事实​​​​​​​​​​​​​​

 声明粒度

数据粒度指数据仓库的数据中保存数据的细化程度或综合程度的级别。

声明粒度意味着精确定义事实表中的一行数据表示什么,应该尽可能选择最小粒度,以此来应各种各样的需求。

典型的粒度声明如下:

订单事实表中一行数据表示的是一个订单中的一个商品项。

支付事实表中一行数据表示的是一个支付记录。

 确定维度

维度的主要作用是描述业务是事实,主要表示的是“谁,何处,何时”等信息。

确定维度的原则是:后续需求中是否要分析相关维度的指标。例如,需要统计,什么时间下的订单多,哪个地区下的订单多,哪个用户下的订单多。需要确定的维度就包括:时间维度、地区维度、用户维度。

确定事实

此处的“事实”一词,指的是业务中的度量值(次数、个数、件数、金额,可以进行累加),例如订单金额、下单次数等。

在DWD层,以业务过程为建模驱动,基于每个具体业务过程的特点,构建最细粒度的明细层事实表。事实表可做适当的宽表化处理。

DWS层与DWT层基于业务需求,与维度建模无关)(数据服务层和数据主题层)

DWS层和DWT层统称宽表层,这两层的设计思想大致相同,通过以下案例进行阐述。

1)问题引出:两个需求,统计每个省份订单的个数、统计每个省份订单的总金额

2)处理办法:都是将省份表和订单表进行join,group by省份,然后计算。同样数据被计算了两次,实际上类似的场景还会更多。

那怎么设计能避免重复计算呢?

针对上述场景,可以设计一张地区宽表,其主键为地区ID,字段包含为:下单次数、下单金额、支付次数、支付金额等。上述所有指标都统一进行计算,并将结果保存在该宽表中,这样就能有效避免数据的重复计算。

3)总结:

(1)需要建哪些宽表:以维度为基准。

(2)宽表里面的字段:是站在不同维度的角度去看事实表,重点关注事实表聚合后的度量值。

(3)DWS和DWT层的区别:DWS层存放的所有主题对象当天的汇总行为,例如每个地区当天的下单次数,下单金额等,DWT层存放的是所有主题对象的累积行为,例如每个地区最近7天(15天、30天、60天)的下单次数、下单金额等。

ADS

对电商系统各大主题指标分别进行分析。

Hive引擎包括:默认MR、tez、spark

Hive on Spark:Hive既作为存储元数据又负责SQL的解析优化,语法是HQL语法,执行引擎变成了Spark,Spark负责采用RDD执行。

Spark on Hive : Hive只作为存储元数据,Spark负责SQL解析优化,语法是Spark SQL语法,Spark负责采用RDD执行。

数仓搭建:

ODS层(用户行为数据与业务数据)

用户行为数据——日志表

业务数据——活动信息表,活动规则表,品类表,订单表,订单明细表,支付表,退款表,SPU表,SKU表等。

1)保持数据原貌不做任何修改,起到备份数据的作用。

2)数据采用LZO压缩,减少磁盘存储空间。100G数据可以压缩到10G以内

3)创建分区表,防止后续的全表扫描,在企业开发中大量使用分区表。

4)创建外部表。在企业开发中,除了自己用的临时表,创建内部表外,绝大多数场景都是创建外部表。

DIM层(维度层)

商品维度表(同步策略:全量)

优惠券维度表(同步策略:全量)

活动维度表(同步策略:全量)

地区维度表(同步策略:特殊)

时间维度表(同步策略:特殊)

用户拉链表(同步策略:新增及变化)

拉链表的概念:

拉链表,记录每条信息的生命周期,一旦一条记录的生命周期结束,就重新开始一条新的记录,并把当前日期放入生效日期。如果当前信息有效,在结束日其中放入一个极大值,例如9999-99-99

拉链表适合于:数据会发生变化,但变化频率不高的维度(即:缓慢变化维)

拉链表的使用:  生效开始日期<=某个日期且生效结束日期=>某个日期,得到某个时间点的时间切片

拉链表形成:

分区:分为过期用户数据和最新用户数据(9999-99-99)

思路:

   获取9999-99-99分区的最新数据与ods层当日分区新增及变化进行full join,一张表为new,一张表为old,进行full join之后,取出所有new表中的字段以及old表中的字段,再利用nvl函数取出join之后字段不为null的值(取出当前最新的记录)再union上old表当过期的记录(end_date为当天),再进行基于dt动态分区,写入到过期变化和最新变化当中

DWD

1)对用户行为数据解析。

2)对业务数据采用维度模型重新建模。

    

进行一些数据的简单清洗,然后利用get_json_object函数将 ods层中数据的公共字段信息抽取出来形成基础明细表,该表主要包括的是公共字段、事件类型、事件具体信息Json格式数据,最后利用UDTF函数对上一步中的基础明细表对事件Json数据进行解释,将里面的每个事件单独抽取形成1个表。

用户行为日志(使用):

启动日志解析思路:启动日志表中每行数据对应一个启动记录,一个启动记录应该包含日志中的公共信息和启动信息。先将所有包含start字段的日志过滤出来,然后使用get_json_object函数解析每个字段。

   错误日志解析思路:错误日志表中每行数据对应一个错误记录,为方便定位错误,一个错误记录应当包含与之对应的公共信息、页面信息、曝光信息、动作信息、启动信息以及错误信息。先将包含err字段的日志过滤出来,然后使用get_json_object函数解析所有字段。

     曝光日志解析思路:曝光日志表中每行数据对应一个曝光记录,一个曝光记录应当包含公共信息、页面信息以及曝光信息。先将包含display字段的日志过滤出来,然后通过UDTF函数,将display数组“炸开”(类似于explode函数的效果),然后使用get_json_object函数解析每个字段。

 

页面日志解析思路:页面日志表中每行数据对应一个页面访问记录,一个页面访问记录应该包含日志中的公共信息和页面信息。先将所有包含page字段的日志过滤出来,然后使用get_json_object函数解析每个字段。

   

    动作日志解析思路:动作日志表中每行数据对应用户的一个动作记录,一个动作记录应当包含公共信息、页面信息以及动作信息。先将包含action字段的日志过滤出来,然后通过UDTF函数将action数组“炸开”(类似于explode函数的效果),然后使用get_json_object函数解析每个字段。

 自定义的UDTF函数的使用(曝光和动作):

代码思路:

  设置对象检查器,判断参数长度和类型是否合法(只接收基础数据,参数必须为string),获取传入后的数据// 1 获取传入的数据

        String jsonArray = objects[0].toString();

        // 2 将string转换为json数组

        JSONArray actions = new JSONArray(jsonArray);

        // 3 循环一次,取出数组中的一个json,并写出

        for (int i = 0; i < actions.length(); i++) {

            String[] result = new String[1];

            result[0] = actions.getString(i);

            forward(result);

        }

Reusult是定义好的返回类型和值

创建函数

(1)打包

(2)将hivefunction-1.0-SNAPSHOT.jar上传到hadoop102的/opt/module,然后再将该jar包上传到HDFS的/user/hive/jars路径下

[atguigu@hadoop102 module]$ hadoop fs -mkdir -p /user/hive/jars

[atguigu@hadoop102 module]$ hadoop fs -put hivefunction-1.0-SNAPSHOT.jar /user/hive/jars

(3)创建永久函数与开发好的java class关联

create function explode_json_array as 'com.atguigu.hive.udtf.ExplodeJSONArray' using jar 'hdfs://hadoop102:8020/user/hive/jars/hivefunction-1.0-SNAPSHOT.jar';

(4)注意:如果修改了自定义函数重新生成jar包怎么处理?只需要替换HDFS路径上的旧jar包,然后重启Hive客户端即可。

业务数据:

评价事实表、订单明细事实表、退单事实表(事务型事实表,每日增量同步)

加购事实表、收藏事实表(周期型快照事实表,每日快照,每日全量同步)

优惠券领用事实表、支付事实表、退款事实表、订单事实表(累积型快照事实表,每日新增变化数据需要分别写入当天完成记录分区以及9999-99-99分区未完成记录当中)

每日数据同步思路:

9999-99-99截止前一日的未完成记录与ODS当日分区中的新增变化进行full join,用nvl函数去判断两张表当中不为NULL的字段并取出,判断当前记录是否有完成再根据完成日期写入到当天的完成记录分区中,未完成的记录则继续写入9999-99-99分区( 如果有多个可以表示完成的时间维度,可以用coalesce代替nvl)

DWS

访客主题

各维度对象当日汇总

访客主题,用户主题,商品主题,优惠券主题,活动主题,地区主题。

访客主题:

从dwd_page_log获取信息,基于用户设备id进行分组统计,计算访客的设备品牌、设备型号、是否首次访问、地区ID、应用版本等信息,利用collect_set函数对name_struct聚合的页面详细访问信息进行去重。ods_page_log中,同一天内,同一设备的is_new字段,可能全部为1,可能全部为0,也可能部分为0,部分为1(卸载重装),来判断是否为新用户,对is_new字段利用collect_set进行聚合,arry_contains来判断

用户主题:

基于日期和用户id进行聚合,从DWD层中获取数据,对订单金额,支付次数,退单次数,登录次数等进行统计计算,利用sum和if函数判断加入购物车或者添加到喜爱的次数再进行聚合,date_fromat函数来统计某年某日某月的访客访问明细。

商品主题:

dwd_order_detail中获得商品项目信息,基于dt和skuid进行聚合统计,统计聚合出商品的优惠金额,订单金额,被退款次数,好评数等信息。

优惠券主题:

基于dt和coupon_id进行分组聚合,对优惠券ID进行统计得出优惠券是总数,通过using_time,exprie_time等判断优惠券的使用情况,同时统计出优惠券的减免金额,订单的原金额以及最终金额,使用full out join 进行连接,利用nvl与coalesce函数进行判断筛选,最后计算出结果。

活动主题表:

 dwd_order_detail表当中获得信息,基于活动id,活动规则和时间进行分组统计,从订单明细表当中获得活动规则,减免金额,优惠金额与支付表当中的订单id进行join,得到某一天的活动与订单支付情况。

地区主题:

基于dwd_order_info以及退单表,页面访问表等,获取基于省份的退单数,访问次数,用户数,支付数等。将全部信息聚合计算,再进行union形成该主题表​​​​​​​

DWT层

访客主题,用户主题,商品主题,优惠券主题,活动主题,地区主题。

不同点:  DWS层注重的是每日维度对象的汇总,DWT层是注重1,7,30天等一段时间内的时间汇总。

数仓搭建-ADS层

访客分析:

该需求为访客综合统计,其中包含若干指标,以下为对每个指标的解释说明。

指标

说明

对应字段

访客数

统计访问人数

uv_count

页面停留时长

统计所有页面访问记录总时长,以秒为单位

duration_sec

平均页面停留时长

统计每个会话平均停留时长,以秒为单位

avg_duration_sec

页面浏览总数

统计所有页面访问记录总数

page_count

平均页面浏览数

统计每个会话平均浏览页面数

avg_page_count

会话总数

统计会话总数

sv_count

跳出数

统计只浏览一个页面的会话个数

bounce_count

跳出率

只有一个页面的会话的比例

bounce_rate

该需求的关键点为会话的划分,总体实现思路可分为以下几步:

第一步:对所有页面访问记录进行会话的划分。

第二步:统计每个会话的浏览时长和浏览页面数。

第三步:统计上述各指标。

count(distinct(mid_id)) uv_count,  

    cast(sum(duration)/1000 as bigint) duration_sec,

    cast(avg(duration)/1000 as bigint) avg_duration_sec,

    sum(page_count) page_count,

    cast(avg(page_count) as bigint) avg_page_count,

    count(*) sv_count,

    sum(if(page_count=1,1,0)) bounce_count,

    cast(sum(if(page_count=1,1,0))/count(*)*100 as decimal(16,2)) bounce_rate

路径分析桑基图

用户路径分析,顾名思义,就是指用户在APP或网站中的访问路径。为了衡量网站优化的效果或营销推广的效果,以及了解用户行为偏好,时常要对访问路径进行分析。

思路分析:该需求要统计的就是每种跳转的次数,故理论上对source/target进行分组count()即可。统计时需注意以下两点:

第一点:桑基图的source不允许为空,但target可为空。

第二点:桑基图所展示的流程不允许存在环。

用户统计

该需求为用户综合统计,其中包含若干指标,以下为对每个指标的解释说明。

指标

说明

对应字段

新增用户数

统计新增注册用户人数

new_user_count

新增下单用户数

统计新增下单用户人数

new_order_user_count

下单总金额

统计所有订单总额

order_final_amount

下单用户数

统计下单用户总数

order_user_count

未下单用户数

统计活跃但未下单用户数

no_order_user_count

用户留存率:

从dws层当中获取数据,对login_date_first进行一个group by,针对login_date_first去时间切片,要求是1-7天的留存率(login_date_first>=date_add('2020-06-14',-7) and login_date_first<'2020-06-14' ) datediff计算日期间隔,判断最后登录日期是否为log_date_last,计算留存用户数,count所有信息计算当天新增用户,最后留存用户除以新增用户得到留存率

品牌复购率:

从dim_sku_info与dwd_order_detail当中获得recen_day,user_id,sku_id等信息,两表join之后,对group by recent_days,user_id,tm_id,tm_name最后对order_count进行判断,订单数大于2/购买过该商品的总次数得到复购率

cast(sum(if(order_count>=2,1,0))/sum(if(order_count>=1,1,0))*100 as decimal(16,2))

订单统计:

dwt_user_topic当中获取最近日期,用户id以及对不同的最近日期进行匹配(订单数和金额),再对order进行求和计算得到订单总数,订单总金额和下单总人数。

各地区订单统计:

       该需求包含各省份订单总数和订单总金额。

      从dwt_area_topicdim_base_province表当中获取基于地区的订单信息以及地区表中的对应id,并进行join,利用case when对不同的最近日期进行匹配(订单数和金额),

优惠券统计:

该需求要求统计最近30日发布的所有优惠券的领用情况和补贴率,补贴率是指,优惠金额与使用优惠券的订单的原价金额的比值。

dwt_coupon_topicdim_coupon_info当中获取信息,获得不同订单的优惠金额以及条件,还有优惠券id,订单原价总价,优惠金额等信息,两表join之后,计算得出优惠率order_reduce_amount/order_original_amount as decimal(16,2)

活动主题:

该需求要求统计最近30日发布的所有活动的参与情况和补贴率,补贴率是指,优惠金额与参与活动的订单原价金额的比值。

dwt_activity_topicdim_activity_rule_info当中获取到信息,两表join之后计算dwt_activity_topic表当中的订单金额,活动优惠金额,将全部的订单优惠金额/订单本身原价金额得到优惠率。

即席查询优化:

Kylin:

使用衍生维度(derived dimension)

衍生维度用于在有效维度内将维度表上的非主键维度排除掉,并使用维度表的主键(其实是事实表上相应的外键)来替代它们。Kylin会在底层记录维度表主键与维度表其他维度之间的映射关系,以便在查询时能够动态地将维度表的主键“翻译”成这些非主键维度,并进行实时聚合。

虽然衍生维度具有非常大的吸引力,但这也并不是说所有维度表上的维度都得变成衍生维度,如果从维度表主键到某个维度表维度所需要的聚合工作量非常大,则不建议使用衍生维度。

使用聚合组(Aggregation group)

聚合组(Aggregation Group)是一种强大的剪枝工具。聚合组假设一个Cube的所有维度均可以根据业务需求划分成若干组(当然也可以是一个组),由于同一个组内的维度更可能同时被同一个查询用到,因此会表现出更加紧密的内在关联。

1强制维度(Mandatory),如果一个维度被定义为强制维度,那么这个分组产生的所有Cuboid中每一个Cuboid都会包含该维度。每个分组中都可以有0个、1个或多个强制维度。如果根据这个分组的业务逻辑,则相关的查询一定会在过滤条件或分组条件中,因此可以在该分组中把该维度设置为强制维度。

2)层级维度(Hierarchy),每个层级包含两个或更多个维度。假设一个层级中包含D1,D2…Dn这n个维度,那么在该分组产生的任何Cuboid中, 这n个维度只会以(),(D1),(D1,D2)…(D1,D2…Dn)这n+1种形式中的一种出现。每个分组中可以有0个、1个或多个层级,不同的层级之间不应当有共享的维度。如果根据这个分组的业务逻辑,则多个维度直接存在层级关系,因此可以在该分组中把这些维度设置为层级维度。

3联合维度(Joint),每个联合中包含两个或更多个维度,如果某些列形成一个联合,那么在该分组产生的任何Cuboid中,这些联合维度要么一起出现,要么都不出现。每个分组中可以有0个或多个联合,但是不同的联合之间不应当有共享的维度(否则它们可以合并成一个联合)。如果根据这个分组的业务逻辑,多个维度在查询中总是同时出现,则可以在该分组中把这些维度设置为联合维度。

Row Key优化底层原理是基于Hbase的rowkey排序

Kylin会把所有的维度按照顺序组合成一个完整的Rowkey,并且按照这个Rowkey升序排列Cuboid中所有的行。

设计良好的Rowkey将更有效地完成数据的查询过滤和定位,减少IO次数,提高查询速度,维度在rowkey中的次序,对查询性能有显著的影响。

Row key的设计原则如下:

  1. 被用作过滤的维度放在前边。

因为Habse当中rowke是按照顺序排列的,将需要过滤的rowkey顺序排列可以加速HBASE的检索读写,提高查询性能

基数大的维度放在基数小的维度前边。

以上图说明这样做的好处,一开始的四维1111分解为三维的时候有四种情况,这里列出两种情况1110和1101。当分解为二维的情况1100的时候,这个二维的1100的数据既可以从三维1110取也可以从三维1101取。Kylin内部的机制是从id小的取,也就是从1101取。1101的D有3条数据,而1110的C有6条数据。所以从1101取数据聚合的数据量更小,效率更好。为什么C的数据量比D大了?这就是因为我们一开始对四维的维度排序的时候是按照基数大小ABCD排序的,而不是按照ABDC来排序的。

Presto优化:

只选择使用的字段

过滤条件必须加上分区字段

对于有分区的表,where语句中优先使用分区字段进行过滤。acct_day是分区字段,visit_time是具体访问时间。

 Group By语句优化

合理安排Group by语句中字段顺序对性能有一定提升。将Group By语句中字段按照每个字段distinct数据多少进行降序排列。

 Order by时使用Limit

Order by需要扫描数据到单个worker节点进行排序,导致单个worker需要大量内存。如果是查询Top N或者Bottom N,使用limit可减少排序计算和内存压力。

使用Join语句时将大表放在左边(大小表join)

Presto中join的默认算法是broadcast join,即将join左边的表分割到多个worker,然后将join右边的表数据整个复制一份发送到每个worker进行计算。如果右边的表数据量太大,则可能会报内存溢出错误。

项目问题及优化:

LZO索引失效

Hive读取索引文件问题

(1)两种方式,分别查询数据有多少行 

hive (gmall)> select * from ods_log;

Time taken: 0.706 seconds, Fetched: 2955 row(s)

hive (gmall)> select count(*) from ods_log;

2959

(2)两次查询结果不一致。

原因是select * from ods_log不执行MR操作,直接采用的是ods_log建表语句中指定的DeprecatedLzoTextInputFormat,能够识别lzo.index为索引文件。

select count(*) from ods_log执行MR操作,会先经过hive.input.format,其默认值为CombineHiveInputFormat,其会先将索引文件当成小文件合并,将其当做普通文件处理。更严重的是,这会导致LZO文件无法切片。

hive (gmall)> 

hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

解决办法:修改CombineHiveInputFormatHiveInputFormat

hive (gmall)> 

set hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;

YARN参数调优yarn-site.xml

(1)情景描述:总共7台机器,每天几亿条数据,数据源->Flume->Kafka->HDFS->Hive

面临问题:数据统计主要用HiveSQL,没有数据倾斜,小文件已经做了合并处理,开启的JVM重用,而且IO没有阻塞,内存用了不到50%。但是还是跑的非常慢,而且数据量洪峰过来时,整个集群都会宕掉。基于这种情况有没有优化方案。

(2)解决办法:

NodeManager内存和服务器实际内存配置尽量接近,如服务器有128g内存,但是NodeManager默认内存8G,不修改该参数最多只能用8G内存。NodeManager使用的CPU核数和服务器CPU核数尽量接近。

①yarn.nodemanager.resource.memory-mb NodeManager使用内存数

②yarn.nodemanager.resource.cpu-vcores NodeManager使用CPU核数

HDFS上的小文件

Sink:HDFS Sink

(1)HDFS存入大量小文件,有什么影响?

元数据层面:每个小文件都有一份元数据,其中包括文件路径,文件名,所有者,所属组,权限,创建时间等,这些信息都保存在Namenode内存中。所以小文件过多,会占用Namenode服务器大量内存,影响Namenode性能和使用寿命

计算层面:默认情况下MR会对每个小文件启用一个Map任务计算,非常影响计算性能。同时也影响磁盘寻址时间。

(2)HDFS小文件处理

官方默认的这三个参数配置写入HDFS后会产生小文件,hdfs.rollInterval、hdfs.rollSize、hdfs.rollCount

基于以上hdfs.rollInterval=3600,hdfs.rollSize=134217728,hdfs.rollCount =0几个参数综合作用,效果如下:

文件在达到128M时会滚动生成文件

文件创建超3600时会滚动生成文件

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值