Hive - 数据流转与DDL设计
数据流转设计
表的分类
- 按所有权分类可分为:外部表(外表)和托管表(内部表、内表)。
- 按表的存储格式分类可分为:Text表、Orc表、Torc表、Holodesk表、Hyperbase表、ES表
- 按表是否分区可分为:分区表和非分区表
- 按表是否分桶可分为:分桶表和非分桶表
表的应用场景
- 数据集市交互式分析:Holodesk
- 数据仓库统计分析/批处理(批量+CURD):ORC事务表/Holodesk、ORC表/Holodesk
- 高并发精确检索:Hyperbase(数据)+全局索引(索引)
- 全文检索:Hyperbase(数据)+ Search(索引)、Search
- 综合搜索:Search
T+1 数据流转
T+1 是数据仓库领域最为常见的数据集成模式,结构化数据来源一般为RDB。需要将这些数据通过ETL工具或者增量导入到HDFS中,最后根据实际业务需求通过inceptor将数据写入到对应的表中。
① sqoop/tdt 支持全量/增量导入数据,可以装载到hdfs中,tdt可以直接写入orc表中
② 需要做大量聚合分析的写入orc表或者argodb表,有数据合并、删除、修改操作的写入orc事务表或者argodb表高并发的精确查询写入hyperbase表
精确查询、模糊查询、多维度灵活组合查询写入Search表
准实时同步数据流转
越来越多数据仓库向准实时方向演进。
Oracle/DB2/MySQL 可以通过部署CDC(如ogg、canal)+Transporter,实现准实时地将数据录入到集群中。之后根据业务需求选择合适的表:
① 数据集市
② 高并发精确检索
③ 综合搜索
实时数据流转
通过Kafka接入实时数据,数据来源可以是kafka/flume/java程序等等,经过slipstream的处理,之后根据实际业务需求,将数据入库到TDH中
① 处理后的数据再次进入kafka,之后对数据再进一步处理,这样的情况一般是kafka作为数据总线的情况,不同的业务通过slipstream去不断地和kafka进行数据上的交互
② 入库Argodb的目的是为了进行准实时的数据分析,有一个前提是对于数据的实时性要求不能太高,在秒级别
③ 经过slipstream(spark/flink)处理后录入到holodesk/Search/Hyperbase的数据可以继续通过ArgoDB将表改变成其他格式,方便其他业务场景的需求。
DDL 设计
表类型 | 存储引擎 | 存储特点 | 支持操作 | 适合场景 |
TEXT表 | hdfs |
行存储,支持无压缩文本,gzip/bzip2压缩格式 |
批量insert和load, truncate 分区分桶 |
多应用于数仓贴源层、ods层、文件交换区;作为临时表,应用于导入或导出时建立的临时表 |
ORC表 | hdfs | 列压缩,压缩比3~8倍 |
批量insert, truncate 分区分桶 |
多用于离线跑批场景,适合做统计分析(如count, join, group by, order by, sum等) |
ORC事务表 | hdfs | 列式存储,压缩比和orc表相近 |
insert,update, merge,delete 分区,分桶(必须) |
相比普通orc表,事务表支持curd、acid,应用于增量数据导入,拉链以及要求事务特性的存储过程中。 |
Holodesk表 | Holodesk | 列式存储,压缩比3~5倍 |
insert,update,merge,delete 分桶 |
交互式分析,应用于自助分析以及BI上拖拉拽生成报表等场景。 |
Hyperbase表 | Hbase | 列族式存储,snappy存储 |
insert,update,delete 分区 |
应用于高并发历史数据查询、精确查询以及非结构化数据存储等场景。 |
ES表 | ElasticSearch | 数据切分为shard存储 |
insert, delete 分区 |
搜索,应用于日志,文本等半结构化/非结构化数据分析场景。 |
分区设计
- 在逻辑上,分区表和未分区表没有区别
- 在物理上,分区表中的数据按分区键的值放在HDFS上表目录下的对应子目录下,一个分区对应一个子目录
- 目的:数据按分区键的值(或值的范围)放在不同目录中,可以有效减少查询时扫描的数据量,提升查询效率。
分区分类
- 单值分区:一个分区对应分区键的一个值
- 范围分区:一个分区对应分区键值的一个范围(区间)
- 不支持范围分区和单值分区混用来进行多层分区
分区设计要点
- 分区字段的取名一定要和数据源表的对应列表相同
- 一般不使用多级分区,但多级分区过滤效果非常出色可以考虑使用
- 分区数控制在0-200个,最大不要超过200个分区
- 建议分区采用range partition
- 建议分区字段选择:日期字段(或地区字段)
- 建议单个分区内桶的数目略小于Inceptor配置的CPU数目
- 设计一个分区数据时,尽量确保一轮CPU能处理完所有数据
- 建议单个分区分桶数在500个以内(分区数 * 分桶数 < 10000 )
分区字段选择
- 一般原则:根据系统的业务类型来选择分区字段
- 例如:
- 通常来讲事实表是数据都包含时间属性,而报表业务也多在一定的时间范围内做统计分析,那么根据时间字段进行分区是常用的选择。
- 而如果业务更多按照部门做统计分析,那么更适合按照部门代码,地域代码进行分区。所以贴近业务的特点选择分区是第一要素。
- 结合数据的分布特点
- 例如:
- 按照用户期望按照某个字段A做分区,但是这个字段A的分布绝对倾斜(譬如字段A一共有1000个不同的数值,但是50%的值都是0,假如按照这个字段分区,那么对应的分区就占了全表50%的数据,这样会导致SQL业务的低效),这个时候选择字段A就不是一个合理的选择。
- 例如:
- 注意数据倾斜问题
- 只要数据分布不是绝对倾斜,我们是可以通过Range分区指定不同大小的方式来有效的规避倾斜问题的。因为,上一个例子的场景中,还是可以选用字段A用于数据分区。
- 例如:
- 企业用户数据,假如2016年用户数是2015年的3倍,我们在选择分区的时候2016年按照1个月为1个分区,而2015年每三个月为一个分区,而不是简单的数值等值切分Range。另外一个常见的情况是按照地域进行分区,我们建议把业务量较多的地域单独放在一个区,其余业务量不多的地域进行整合,从而保证各个区之间数据量大致均衡,避免出现大部分分区没有数据或者数据非常少的情况。如果发现某些区数据特别倾斜,则需要考虑进一步或者更换分区字段。
- 生产上一般建议使用时间字段做范围分区,并根据数据的每天和每月增量的大小来界定每个分区的范围。
分区个数选择
- 分区个数的选择需要综合考量数据的特性,在选择好分区字段后,我们需要根据数据的特点确定分区个数的可选择区间。
- 实际情况中我们看到多数DDL设计都是分区数量过多,譬如单个分区的数据量不超过1GB,或者按照天来分区,这些都是不合适的设计。
- 生产上一般我们建议分区数量在100以内。
ORC表分区示例
某客户生产上有一张表,tb_fct_vip_s_det_m总记录数9亿多条。有时间字段statmt,并且ETL作业中会频繁使用该字段过滤某一天的数据。每月的数据量大概在3000万条。考虑到如果按天分区会导致分区数过多,但又要尽可能的减少执行SQL时扫表的数据量,所以采用按月分区的方案。对表做了5年规划,共61个分区。
CREATE TABLE tb_fct_vip_s_det_m(
statsdt date NOT NULL COMMENT '统计日期',
...
currmonthtotalfavamt decimal(14,2) DEFAULT NULL COMMENT '本月累计优惠金额'
)
PARTITIONED BY RANGE(
statsdt COMMENT '统计日期')(
PARTITION stats_less_than_201401 VALUES LESS THAN('2014-01-01'),
PARTITION stats_less_than_201402 VALUES LESS THAN('2014-02-01'),
PARTITION stats_less_than_201403 VALUES LESS THAN('2014-03-01'),
...
PARTITION stats_less_than_201812 VALUES LESS THAN('2018-12-01'),
PARTITION stats_less_than_maxvalue VALUES LESS THAN(MAXVALUE))
CLUSTERED BY (cporgcd) INTO 19 BUCKETS stored as orc_transactions;
分桶设计
- 分桶字段选择
- 进行分桶之前需要对表的数据分布情况进行大致的分析,一般遵循的原则为,选择离散高的字段进行分桶。可以通过收集的数据特征,如Distinct Value来做参考,值越大的可以优先作为考虑对象。分桶字段选择时,注意尽量使记录分布均匀,以避免数据倾斜。
- 建议分桶字段:关系型数据库中的主键、邮件ID、客户ID、UUID等。
- 分桶个数选择
- 一般可以通过数据量维度计算分桶个数。
- 根据数据量计算分桶数公式:分桶数 = 文本格式大小(M)/500M
- 在考虑分桶个数的时候,同时要考虑是否已经分过区。对于已经分过区的表,要按照单区的大小进行桶数的估计,而不是依照原始表。
- 对表分桶可以将表中记录按分桶键的哈希值分散进多个桶文件中,这些文件被称为“桶”
- 一个表可以同时进行分区和分桶
- 分桶有三方面的好处:
- 有助于快速取样
- 减少操作量,提高查询效率
- 减少Shuffle的数量
分桶示例
某客户在数据仓库建设的过程中,有如下一张大表,PIMS_PMART2.TB_FCT_VIP_S_DET_FL_M,总大小为23.5亿条,ORC格式24.8G,61个分区,31个桶,目前的分桶字段为collcporgcd,查看某个分区下每个桶的大小情况,如下:发现桶的大小极不均匀,有的桶265M,有的桶只有2.9M,这种是典型的分桶字段选择不合理的情况。
Step1:选出合理的分桶字段
- 以(字段中重复值最多的记录数/表的总记录数)的值作为是否可以作为分桶字段的依据。
// 查询字段中重复值最多的记录数
COL_COUNT=select column1,count(1) cnt from table_name group by column1 order by cnt desc limit 1;
// 查询表的总记录数
TOTAL_COUNT=select count(1) from table_name;
- 如果COL_COUNT/TOTAL_COUNT的值小于5%,或者COL_COUNT的值在100万以下,那么该字段可作为分桶字段。
- 特别的,如果一个表中确实找不到分布均匀的字段作为分桶,可以单独对表追加一个唯一ID作为分桶字段。
- 以该表为例,通过对该表每个字段做分析发现,custcd这个字段COL_COUNT=2114438,TOTAL_COUNT=2357030761,两者比值仅为0.09%,非常适合作为分桶字段。
Step2:算出合理的分桶数
- 该表已经存在数据的分区每个分区约6000万条记录,ORC格式700M。
- 根据计算公式:分桶数=MAX(6000万/100万,700M/100M)=60
- 为了使数据分布更加均匀,我们一般建议选择质数作为分桶数
- 所以该表的最佳分桶数为59或61
ORC表建表语法
ORC非事务表的建表只需在建表语句中用 stored as orc
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [<database_name>.]<table_name>
[(<col_name> <data_type> [COMMENT '<col_comment>'][,<col_name> <data_type>...])]
[COMMENT '<table_comment>']
...
[STORED AS ORC]
[LOCATION '<file_path>']
[TBLPROPERTIES ('<property_name>'='<property_value>',...)];
非分区表建表语法:
CREATE TABLE <table_name> (<column> <data_type>,<column> <data_type>,...)
CLUSTERED BY (<bucket_key>) INTO <n> BUCKETS
STORED AS ORC
TBLPROPERTIES("transactional"="true");
单值分区表(Unique Value Partition)建表语法:
CREATE TABLE <table_name> (<column> <data_type>,<column> <data_type>, ...)
PARTITIONED BY (<partition_key> <data_type>)
CLUSTERED BY (<bucket_key>) INTO <n> BUCKETS
STORED AS ORC
TBLPROPERTIES("transactional"="true");
范围分区表(Range Partition) 建表语法:
CREATE TABLE <table_name> (<column> <data_type>,<column> <data_type>, ...)
PARTITIONED BY RANGE(<partition_key1> <data_type>,<partition_key2> <data_type>, ...)
(
PARTITION [<partition_name_1>] VALUE LESS THAN(<key1_bound_value1>, <key2_bound_value1>,...),
PARTITION [<partition_name_2>] VALUE LESS THAN(<key1_bound_value2>, <key2_bound_value2>,...),
...
)
CLUSTERED BY (<bucket_key>) INTO <n> BUCKETS
STORED AS ORC
TBLPROPERTIES("transactional"="true");
小结
- ORC非事务表的建表只需在建表语句中用
STORED AS ORC
指定存储格式为ORC即可。 - ORC事务表的建表则需要几个额外的重点步骤:
- 为表分桶:为了保证增删改过程中的性能,我们要求ORC事务表必须是部分排序或者全局排序的,但是全局排序又过于耗费计算资源,因此我们要求ORC表必须是分桶表
- 在
TBLPROPERTIES
里需要加上"transactional"="true"
,以标识ORC表必须是分桶表 - 如果表的数据量比较大,建议在分桶的基础上再分区,ORC事务表支持单值分区和范围分区。
Hive - 数据流转与DDL设计的更多相关文章
- Hive数据据类型 DDL DML
Hive的基本数据类型 DDL DML: 基本数据类型 对于Hive而言String类型相当于数据库的varchar类型,该类型是一个可变的字符串,不过它不能声明其中最多能存储多少个字符,理论上它可以 ...
- Hive数据类型和DDL操作
hive命令 在Linux下的命令行中直接输入如下命令,可以查看帮助信息: # hive -help 常用的如-e.-f参数. 使用-e参数,可以直接在命令行传递SQL语句进行hive表数据的查询: ...
- 三:基于Storm的实时处理大数据的平台架构设计
一:元数据管理器==>元数据管理器是系统平台的“大脑”,在任务调度中有着重要的作用[1]什么是元数据?--->中介数据,用于描述数据属性的数据.--->具体类型:描述数据结构,数据的 ...
- 面向UI编程:ui.js 1.1 使用观察者模式完成组件之间数据流转,彻底分离组件之间的耦合,完成组件的高内聚
开头想明确一些概念,因为有些概念不明确会导致很多问题,比如你写这个框架为什么不去解决啥啥啥的问题,哎,心累. 什么是框架? 百度的解释:框架(Framework)是整个或部分系统的可重用设计,表现为一 ...
- 大数据平台Hive数据迁移至阿里云ODPS平台流程与问题记录
一.背景介绍 最近几天,接到公司的一个将当前大数据平台数据全部迁移到阿里云ODPS平台上的任务.而申请的这个ODPS平台是属于政务内网的,因考虑到安全问题当前的大数据平台与阿里云ODPS的网络是不通的 ...
- Hive数据如何同步到MaxCompute之实践讲解
摘要:本次分享主要介绍 Hive数据如何迁移到MaxCompute.MMA(MaxCompute Migration Assist)是一款MaxCompute数据迁移工具,本文将为大家介绍MMA工具的 ...
- sqoop用法之mysql与hive数据导入导出
目录 一. Sqoop介绍 二. Mysql 数据导入到 Hive 三. Hive数据导入到Mysql 四. mysql数据增量导入hive 1. 基于递增列Append导入 1). 创建hive表 ...
- Nebula Exchange 工具 Hive 数据导入的踩坑之旅
摘要:本文由社区用户 xrfinbj 贡献,主要介绍 Exchange 工具从 Hive 数仓导入数据到 Nebula Graph 的流程及相关的注意事项. 1 背景 公司内部有使用图数据库的场景,内 ...
- 从零自学Hadoop(17):Hive数据导入导出,集群数据迁移下
阅读目录 序 将查询的结果写入文件系统 集群数据迁移一 集群数据迁移二 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephis ...
- hadoop数据流转过程分析
hadoop:数据流转图(基于hadoop 0.18.3):通过一个最简单的例子来说明hadoop中的数据流转. hadoop:数据流转图(基于hadoop 0.18.3): 这里使用一个例子说明ha ...
随机推荐
- PM-CentOS7也即将停止维护,将来何去何从?
停掉的CentOS包含三个版本,即:CentOS 6(2020年11月30日停止更新).CentOS7(2024年6月30日停止更新).CentOS 8(2021年底停止更新). 在当前处于生命周期中 ...
- 叮咚~ 你的Techo大会云存储专场邀请函到了!
12月19日至20日,由腾讯主办的2020 Techo Park开发者大会将于北京召开.Techo Park 开发者大会是由腾讯发起的面向全球开发者和技术爱好者的年度盛会,作为一个专注于前沿技术研讨的 ...
- Java线程 interrupt 方法使用异常
背景 需要在异步任务中中断任务的执行,故选择通过调用 interrupt 方法对线程设置中断信号. 在比较耗时的业务代码增加判断 Thread.currentThread().isInterrupte ...
- forms组件与源码分析、modelform组件
目录 一.forms组件 forms组件介绍 Form定义 二.forms组件渲染标签 三.forms组件展示信息 四.forms组件校验补充 五.forms组件参数补充 六.forms组件源码剖析 ...
- win10 ocx控件注册失败的解决办法
首先注意:ocx放在大部分系统目录无法注册,比如program file ,但windows目录可以. 第一步:关闭防火墙 第二步:确定是否缺少控件运行需要的微软运行库或其他运行环境 这里提供一个挺全 ...
- java到报名的编码运行
Hello.java package a.b; import com.beyondiary.kit.KitConstant; public class Hello { public static vo ...
- Unity 3D简单使用C#脚本,脚本的执行顺序
Unity3D脚本间执行顺序 Unity3D中一个场景有时候需要多个脚本,可以挂在同一物体上执行,也可以挂在不同物体上执行 那么执行顺序是怎样的?我们来测试下 在上个项目基础上,再建一个Test2脚本 ...
- Wasm在即时通讯IM场景下的Web端应用性能提升初探
本文由得物技术WWQ分享,原题"基于IM场景下的Wasm初探:提升Web应用性能",下文进行了排版和内容优化. 1.什么是Wasm Wasm,全称 WebAssembly,官网描述 ...
- 【记录】使用R2 CDN替换本地项目图片以加速图片加载
将图片存储到 Cloudflare 的存储桶中,并通过其提供的公共 URL 来替换代码中的本地路径,可以减小项目中打包的图片文件体积 实现方法的详细步骤: 1. 上传图片到 Cloudflare 的存 ...
- 在Quartz .NET的工作类中使用依赖注入
Quartz .NET默认的Execute方法是不支持非空的构造函数的,所以.net core常用的构造函数依赖注入也搞不来,网上搜索一番搞定了这个问题. 解决方案简单来说就是自定义一个任务工厂,替换 ...