MaxCompute表设计最佳实践

MaxCompute表设计最佳实践

产生大量小文件的操做

MaxCompute表的小文件会影响存储和计算性能,所以咱们先介绍下什么样的操做会产生大量小文件,从 而在作表设计的时候考虑避开此类操做。数据库

  • 使用MaxCompute Tunnel SDK上传数据,上传过程当中,每commit一次就会产生一个文件。这时每 个文件太小(好比几K),而且频繁上传(好比5秒上传)一次,则一小时就会产生720个小文件,一 天就会产生17280个小文件。
  • 使用MaxCompute Tunnel SDK上传数据,create了session可是没有upload数据直接作了 commit,产生大量空目录(服务侧等同于小文件)。
  • 使用MaxCompute Console命令行工具Tunnel命令上传时,将本地大文件切分太小,致使上传后产 生文件数过多,文件太小。
  • 经过DataHub作数据归档,Datahub 的每一个shard写 MaxCompute 有两个条件:数据总量达到 64MB,commit 一次到 MaxCompute,造成一个文件。或者每隔 5 分钟一次 commit,造成一个 文件。那么:开的shard数多(好比20个shard),每一个shard数据在5分钟内都远远达不到64M,比 如就是几百K,就会产生大量小文件。那么一天就会产生241220=5760个小文件。
  • 经过Dataworks等数据开发工具进行数据增量插入(insert into)到MaxCompute的表(或者表分 区)里时,每一个insert into都会产生一个文件,若每次insert into 10条,天天累计insert insert 10000条记录,则会产生1000个小文件。
  • 经过阿里云DTS将数据从RDS等数据库同步到MaxCompute,DTS进行数据同步时,会建立全量表和 增量表,增量表进程数据插入过程当中会由于每次数据插入条数较少而commit比较完整一次数据同步, 从而在增量表中形成小文件问题,好比每隔5分支执行一次同步,每次同步的数据量为10条,一天内的 增量为10000条,则会产生1000个小文件。此种场景,须要在数据同步完成后进行全量极限表和增量 数据表的merge。
  • 源数据采集客户端太多,源数据经过T unnel直接进入到一个分区,每一个源数据采集客户端提交一次数 据,都会在同一分区下产生一个独立的文件致使产生大量小文件。
  • SLS 触发 FunctionCompute持续高频往MaxCompute中心接入文件,小文件流式数据进入 MaxCompute。

根据数据划分项目空间

项目空间(Project)是MaxCompute最高层的对象,按项目空间进行资源的分配、隔离和管理,实现了 多租户的管理能力。session

  • 若是多个应用须要共享“数据”,则推荐使用同一个项目空间。
  • 若是多个应用所需“数据”是无关的,则推荐使用不一样的项目空间。 项目空间间的表和分区能够经过Package受权的方式进行交换。

“维度表”设计的最佳实践:

通常状况下描述属性的表设计为维度表。维度表能够和任意表组的任意表进行关联,而且建立时不须要配 置分区信息,可是对单表数据量大小有所限制。维度表的设计和使用注意如下几点:工具

  • 通常要求维度表单表不超过1000万。
  • 维度表的数据不该该被大量更新。
  • 维度表和其余表进行Join操做时可使用mapjoin。

拉链表设计 – 极限存储的应用

极限存储功能待发布,在此介绍主要提供设计思想。 基于MaxCompute的拉链表设计背景 在数据仓库的数据模型设计过程当中,常常会遇到这样的需求:性能

  • 数据量比较大。 表中的部分字段会被update,如用户的地址,产品的描述信息,订单的状态、手机号码等等。
  • 须要查看某一个时间点或者时间段的历史快照信息。(好比,查看某一个订单在历史某一个时间点的 状态,好比,查看某一个用户在过去某一段时间内,更新过几回等等)
  • 变化的比例和频率不是很大,好比,总共有1000万的会员,天天新增和发生变化的有10万左右,若是表天天都保留一份全量,那么每次全量中会保存不少不变的信息,对存储是极大的浪费。 
    考虑极限存储的使用: MaxCompute提供了将不一样表转化为极限存储表的能力。极限存储操做示例以下:
  1. 建立源表。
create table src_tbl (key0 STRING, key1 STRING, col0 STRING, col1 STRING, col2 STRING) PARTITIO N (datestam p_x STRING, pt0 STRING);
  1. 导入数据。
  2. 将src_tbl转变为极限存储的表。
set odps.exstore.primarykey=key0,key1;
[set odps.exstore.ignorekey=col0;]
EXSTO RE exstore_tbl PARTITIO N (datestam p_x='20140801'); EXSTO RE exstore_tbl PARTITIO N (datestam p_x='20140802');

拉链表设计更详细介绍能够参考云栖文章:https://yq.aliyun.com/articles/542146#? spm=a2c41.11181499.0.0开发工具

采集源表的设计

数据采集方式:流式数据写入, 批量数据写入,周期调度条式数据插入。 
大数据量状况下,确保同一个业务单元的数据使用分区和表进行分;在数据量较小状况下,优化采集频率。大数据

  • 流式数据写入。优化

    • 对于流式写入的数据,通常采集的通道较多,相关采集通道应作有效区分,在单个数据通道写入 量较大的状况下应该进行按照时间进行分区设计。
    • 在采集通道数据量较小的状况下能够采起非分区表设计,对终端类型和采集时间设计成标准列字 段。
    • 采用Datahub进行数据写入时应该合理规划shard数量,放置因为shard过多而形成采集通道流量 较小且通道较多的问题。
  • 批量数据写入。批量数据写入重点关注写入周期 周期调度条式数据插入。
  • 避免周期数据插入,此种状况下须要创建分区表,在新分区进行插入操做, 减小对于原来分区影响。

日志表的设计

日志实际上是个流水表,不涉及记录的更新,来一条采集一条,多条一块儿存放,日志表设计的主要注意几 点:阿里云

create table src_tbl (key0 STRING, key1 STRING, col0 STRING, col1 STRING, col2 STRING) PARTITIO N (datestam p_x STRING, pt0 STRING);
  set odps.exstore.primarykey=key0,key1;
[set odps.exstore.ignorekey=col0;]
EXSTO RE exstore_tbl PARTITIO N (datestam p_x='20140801'); EXSTO RE exstore_tbl PARTITIO N (datestam p_x='20140802');
  • 考虑是否须要对日志进行去重处理。
  • 考虑是否须要扩展维度属性。spa

    • 是否须要关联维表扩展维度属性字段考虑两点:业务使用的频次,关联是否会形成的产出的延 迟。
    • 须要仔细选择是否对于维度表进行扩展
  • 考虑区分终端类型。命令行

    • 日志表因为量大,考虑在业务分析使用时一般会按PC端,APP端来统计分析,同时PC端、APP端 的采集是两套体系,所以一般的作法会按终端设计多个明细DWD表。
    • 若是终端较多,但数据量不大的状况下,如一个终端的数据小于1T 可是采集次数较多,能够考虑 不对终端进行分区,而设置终端信息为普通列。

注意:

  • 对于日志表进行分区设计,能够按照日志采集的时间按照天进行分区,在入数据前进行数据采集整 合,一批数据写入提交一次(一般是64M)。
  • 日志数据不多有对原来分区的更新操做,能够采用insert 进行少许数据的插入,但通常须要限制插入 次数。
  • 若是有大量的更新的操做,须要采用insert overwrite操做避免小文件问题。
  • 对日志表设置合理的分区和对已经⻓久不访问的冷热数据配置归档操做。

互动明细表的设计

周期快照表,天天对收藏的全部记录进行快照存放。 
问题:历史累计的记录很是多,天天生成快照要拿当天增量表与前一天的全量表merge,很是耗资源。统 计最近1天的新增收藏数,须要扫描全量表,如何下降资源? 
建议的方案:创建一个事务性事实表,在创建一个存放当前有效收藏的周期快照表,以知足各类不一样业务 的统计分析须要。
注意:

  • 设计互动明细表最重要的是要区分存量数据和增量数据之间的关系。 - 对于新分区的数据能够写入,做为增量数据。
  • 应尽可能减小对于老的分区数据的修改和插入。
  • 在数据插入和全表覆盖写种选择时应尽可能选用insert overwrite而并选择insert into。

MaxCompute表数据更新与删除操做

关系型数据库支持的 delete/update/merge SQL ,在MaxCompute上的实现方式示例以下: 
表准备

-- 上日全量表
table1(key1 string,key2 string,col1 string,col2 string);
-- 今日增量表
table2(key1 string,key2 string,col1 string,col2 string);
​-- 今日增量表(删除)
table3(key1 string,key2 string,col1 string,col2 string);

update(table2 表中的记录的值,更新到table1表中)

insert overwrite table table1 select t1.key1
,t1.key2
,case when t2.key1 is not null then t2.col1 else t1.col1 end as col1 ,case when t2.key1 is not null then t2.col2 else t1.col2 end as col2
from table1 t1
left outer join table2 t2 on t1.key1=t2.key1 and t1.key2 = t2.key2 ;

delete(table2 表中的记录,从table1表中删除)

insert overwrite table table1 select t1.key1
,t1.key2 ,t1.col1 ,t1.col2
from table1 t1
left outer join table2 t2 on t1.key1=t2.key1 and t1.key2 = t2.key2 where t2.key1 is null
;

merge(没有del)

insert overwrite table table1 select
from (
-- 先把上日存在,今日也存在的记录从上日表中排除。剩下的就是今日没有更新的记录 select t1.key1
,t1.key2 ,t1.col1 ,t1.col2
from table1 t1
left outer join table2 t2 on t1.key1=t2.key1 and t1.key2 = t2.key2 where t2.key1 is null
union all
-- 再合并上今日增量,就是今天的全量 select t2.key1
select t2.key1
  ,t2.key2
  ,t2.col1
  ,t2.col2
from table2 t2)tt
;

merge(有del)
insert overwrite table table1 select
from (
-- 先把上日存在,今日也存在的记录从上日表中排除,再把今日删除的记录排除。剩下的就是今日没有更 新的记录

insert overwrite table table1 select
from (
-- 先把上日存在,今日也存在的记录从上日表中排除,再把今日删除的记录排除。剩下的就是今日没有更 新的记录
select t1.key1
,t1.key2 ,t1.col1 ,t1.col2
from table1 t1
left outer join table2 t2 on t1.key1=t2.key1 and t1.key2 = t2.key2 left outer join table3 t3 on t1.key1=t3.key1 and t1.key2 = t3.key2
where t2.key1 is null or t2.key1 is null
union all
-- 再合并上今日增量,就是今天的全量 select t2.key1
,t2.key2 ,t2.col1 ,t2.col2
from table2 t2)tt ;

表建立设计示例

场景:天气状况信息采集。

  • 基本信息: 数据信息包括地名,关于此地的属性数如面积,基本人口数量等信息,天气信息。
  • 属性数据变化较小,天气信息数采用多个终端采集,且数据量较大
  • 天气信息变化较大,终端数量稳定的状况下流量基本稳定。
    表设计指南:
  • 建议对数据信息划分为基本属性表,和天气日志表,区分变化小和变化大的数据。
  • 由于数据量巨大,对天气日志表按照地域进行分区,也能够按照时间如天进行二级分区,此种分区方 式避免因某一地或某一个时间的天气变化而形成其余无关数据变化。
  • 采集终端上使用datahub进行数据汇聚,依据稳定的流量值选择合适的shard通道数量,批量数据方式 写入到天气日志表中,不使用Insert into。

MaxCompute表的特点功能

生命周期

MaxCompute表/分区提供数据生命周期管理。表(分区)数据从最后一次更新时间算起,在通过指定的 时间后没有变更,则此表(分区)将被MaxCompute自动回收。这个指定的时间就是生命周期,生命周期 设置为表级别。

create table test_lifecycle(key string) lifecycle 100;/alter table test_l ifecycle set lifecycle 50;

MaxCompute会根据每张非分区表或者分区的的LastDataModifiedTime以及lifecycle的设置来判断是 否要回收此非分区表或者分区表中的分区。 MaxCompute SQL提供touch操做用来修改分区的 LastDataModifiedTime。会将分区的LastDataModifiedTime修改成当前时间。修改 LastDataModifiedTime的值,MaxCompute会认为表或分区的数据有变更,生命周期的计算会从新开始。

ALTER TABLE table_nam e TO UCH PARTITIO N(partition_col='partition_col_valu e', ...);

注意:

  • 合理规划表的生命周期,在建立表时即设置生命周期,可有效减小存储压力。
  • 对表数据的任何变更都会影响生命周期回收数据的判断时间,包括小文件合并。

避免全表扫描

表设计:

  • 创建分区表或者对扫描条件进行列设计。
  • 对数据表进行合理分区。 对经常使用查询条件设置成列名。
  • 读经常使用查询条件进行hash clustering
    数据计算:
  • 加分区过滤条件,或者减小扫描分区数,或者拆出中间小表而后再扫描小表的历史分区以减小数据扫描 量。
  • 把全局扫描表中间结果进行存储造成中间表。
  • 若是天天都去扫一年的分区,计算消耗是很是大的,建议拆出一张中间表,天天作一次汇总,而后再 去扫描这张中间表的一年分区,扫描数据量会减小不少。

避免小文件

  • Reduce计算过程产生的小文件:只须要insert overwrite源表(或分区)便可,或者写入到新表删除 源表。
  • Tunnel数据采集过程当中产生的小文件建议:

    • 调用tunnelsdk时当buffer达到64M时提交一次;
    • 使用console时避免频繁上传小文件,建议积累较大时一次性上传; 若是导入的是分区表,建议给分区设置生命周期,过时不用的数据自动清理;
    • 同第一种方案,insertoverwrite源表(或分区);
    • ALTER合并模式,经过console命令进行合并。
  • 使用临时表建议建立时都加上生命周期,到期后垃圾回收自动回收。 - 申请过多的datahub shard将会产生小文件问题,申请datahub shard数目的策略 :

    • 默认吞吐量单个shard是1MB/s,能够按照这个分配实际的shard数目(能够在此基础上多加几 个);
    • 同步odps的逻辑是每一个shard有一个单独的task(知足5分钟或者64MB会commit一次),默认设置5分钟是为了尽快能在odps查到数据。若是是按照小时建partition,那个一个shard每一个小 时有12个文件。
    • 若是这个时候数据量不多,可是shard不少,在odps里面就会不少小文件(shard*12/hour)。
    • 不要过多的分配shard,按需分配。

转化Hash Clustering表

Hash Clustering表的优点:优化Bucket Pruning/优化Aggregation/优化存储。 在建立表时使用CLUSTERED BY指定Hash Key,MaxCompute将对指定列进行Hash运算,按照Hash 值分散到各个Bucket里面。
Hash Key指选择原则:

  • 选择重复键值少的列
  • SORTED BY用于指定在Bucket内字段的排序方式。
    如何转化为HashClustering表:
ALTER TABLE table_nam e [CLUSTERED BY (col_nam e [, col_nam e, ...]) [SO RTED B Y (col_nam e [ASC | DESC] [, col_nam e [ASC | DESC] ...])] INTO num ber_of_buck ets BUCKETS]

ALTER TABLE语句适用于存量表,在增长了新的汇集属性以后,新的分区将作hash cluster存储。 建立 完HashClustering的表以后使用insert overwrite从另一个源表进行转化。
注意,Hash Clustering表有如下限制:

  • 不支持insert into,只能经过insert overwrite来添加数据。
  • 不支持tunnel直接upload到range cluster表,由于tunnel上传数据是无序的。

原文连接 

相关文章
相关标签/搜索