大数据计算服务 ( MaxCompute,原名 ODPS ) 是一种快速、完全托管的 TB/PB 级数据仓库解决方案 。MaxCompute 向用户提供了完善的数据导入方案以及多种经典的分布式计算模型,能够更快速的解决用户海量数据计算问题,有效降低企业成本,并保障数据安全 。同时,大数据开发套件和 MaxCompute关系紧密,大数据开发套件为 MaxCompute 提供了一站式的数据同步,任务开发,数据工作流开发,数据管理和数据运维等功能,您可以参见 大数据开发套件简介 来对其进行深入了解 。
MaxCompute 主要服务于批量结构化数据的存储和计算,可以提供海量数据仓库的解决方案以及针对大数据的分析建模服务 。随着社会数据收集手段的不断丰富及完善,越来越多的行业数据被积累下来 。数据规模已经增长到了传统软件行业无法承载的海量数据(百 GB、TB、乃至 PB)级别 。
在分析海量数据场景下,由于单台服务器的处理能力限制,数据分析者通常采用分布式计算模式 。但分布式的计算模型对数据分析人员提出了较高的要求,且不易维护 。使用分布式模型,数据分析人员不仅需要了解业务需求,同时还需要熟悉底层计算模型 。MaxCompute 的目的是为用户提供一种便捷的分析处理海量数据的手段 。用户可以不必关心分布式计算细节,从而达到分析大数据的目的 。
首先 MaxCompute 不同于普通的mysql,oracle这样的关系型数据库,它其实是一个综合性的数据服务平台,它并不能在毫秒级甚至秒级返回查询结果,一条odps命令的执行通常需要经过如下流程:客户端接收到返回的 Instance ID 后,可以通过 Instance ID 来查询作业状态:
CREATE TABLE IF NOT EXISTS xxxx
(
aa STRING COMMENT 'xxxx',
bb STRING COMMENT 'xxxx',
cc STRING COMMENT 'xxxx',
dd STRING COMMENT 'xxxx',
ee STRING COMMENT 'xxxx',
ff STRING COMMENT 'xxx',
gg BIGINT COMMENT 'xxx'
)
COMMENT 'xxxx'
PARTITIONED BY (dt STRING COMMENT '')
LIFECYCLE 10;
在工作流中我们希望任务能够顺利的执行,所以不管是DDL和DML中我们都尽量希望语句返回成功(if not exist,overwrite)
comment包括对应字段的注释和对应表的注释,这些都可以alter
与传统的SQL不同,MaxCompute面向全域数据,所以即使是用create xxxx select xxxx from xxx的方式也需要as加上列的名称。
分区字段注明,由于MaxCompute操作的数据量很大,通常来说分区字段需要特别关注
生命周期:非常方便的属性,便于用户释放存储空间,简化回收数据的流程,不需要传统的繁杂的空间维护。灵活运用LastDataModifiedTime与touch(修改为当前时间),关注分区表和非分区表的区别。
对于大表结构的复制,odps提供非常灵活的create like语句。
alter几乎可以对表的所有属性进行更改,包括列,注释,分区,分区属性,生命周期等等。
insert overwrite|into table tablename
[partition (partcol1=val1, partcol2=val2 ...)]
select_statement
from from_statement;
静态分区,分区字段常量;动态分区,可以不指定值,适用select字句中的分区列值
multi-insert 单次读入,多次写入,减少数据读取。
select [all | distinct] select_expr, select_expr, ...
from table_reference
[where where_condition]
[group by col_list]
[order by order_condition]
[distribute by distribute_condition [sort by sort_condition] ]
[limit number]
与传统的SQL不同的是,distinct作用所有select字段
编译过程group > select > order/sort/distribute,理解了编译顺序也就理解了各个字句间别名的使用规范。 package org.alidata.odps.udf.examples;
import com.aliyun.odps.udf.UDF;
public final class Lower extends UDF {
public String evaluate(String s) {
if (s == null) { return null; }
return s.toLowerCase();
}
}
继承UDF类,实现evaluate方法即可。evaluate方法可以有多个,满足多态特性。
UDAF:
继承com.aliyun.odps.udf.Aggregator,主要实现iterate,merge和terminate三个接口,UDAF的主要逻辑依赖于这三个接口的实现。此外,还需要用户实现自定义的Writable buffer,因为UDAF的主要逻辑是将数据进行分片后遍历,处理完之后进行merge。
UDTF:
继承com.aliyun.odps.udf.UDTF类,主要实现process和forward两个接口,SQL中每一条记录都会对应调用一次process,process的参数为UDTF的输入参数。输入参数以Object[]的形式传入,输出结果通过调用forward函数输出。
DECLARE
var_name var_type;
BEGIN
可执行语句
END;
Shuffle的时候,将各个节点上相同的key拉取到某个节点的一个task进行处理,比如按照key进行聚合或join等操作,如果某个key对应的数据量特别大的话,就会发生数据倾斜现象。数据倾斜就成为了整个task运行时间的短板。
触发shuffle的常见算子:distinct、groupBy、join等。
要解决数据倾斜的问题,首先要定位数据倾斜发生在什么地方,首先是哪个stage,直接在D2 UI上看就可以,查看数据是否倾斜了
logview--odps task--detail--stage--longtail
根据stage日志,判断出数据倾斜发生在哪个算子上。
根据倾斜发生的阶段,我们又可以把它们分为map倾斜,reduce倾斜,join倾斜
通常来说,对于倾斜现象,我们首先查看导致数据倾斜的key的数据分布情况,接下来大概有几种处理方案:
1:过滤数据
过滤掉某些脏数据,比如说是否可以去掉null,去掉某些条件对应的值
2:加大并行度
给任务添加处理资源,加大instance的数量,暴力
3:对数据进行拆分,分而治之
如果大表join小表,我们可以用mapjoin,将小表cache进内存
二次分发,加上随机前缀(数据膨胀),拆分数据集为热点+非热点再进一步处理
大表join超大表,还可以考虑bloomfilter
4:组合使用
上述方法,组合使用
5:修改业务
实在没有进步空间,从业务上过滤数据