天天看点

MaxCompute的分区配置和使用

创建表的时候,可以设置普通列和分区列。在绝大多数情况下,可以把普通列理解成数据文件的数据,而分区列可以理解成文件系统的目录。所以表的存储空间的占用,讲的是普通列的空间占用。分区列虽然不直接存储数据,但是如同文件系统里的目录,可以起到方便数据管理,并在计算只指定具体的分区的时候,只查询对应分区减少计算量的作用。

MaxCompute的分区配置和使用

从这里可以看到分区表的创建方式。目前分区列只支持string类型。bigint目前是还在测试中,并无法保证其计算准确性,暂时还不建议大家使用。

目前分区表的分区列的个数不能超过6级,也可以理解成底层存储数据的目录层数不能超过6层。

分区的作用主要有2部分。其一是能方便数据的管理。使用了分区后,一张表的数据被分到多个不同的分区里。比如日志表如果我们根据日期(天)进行分区,那么每个分区里都是单独一天的数据。如果有一天我们希望能归档历史数据到某个地方,或者删除过旧的数据,就只需要处理对应的分区即可。在这里还需要提一下lifecycle设置生命周期的功能,可以设置数据的过期时间,单位为天。maxcompute 会根据每张表的lastdatamodifiedtime以及lifecycle的设置来判断是否要回收此表。如果这张表是分区表,则根据各分区的lastdatamodifiedtime判断该分区是否该被回收。所以假如设置了过期时间是100天,然后数据是每天同步到一个分区里,历史分区的数据写入后不再修改追加(lastdatamodifiedtime不变),那么100天之前的历史数据会被自动删除,减少运维成本。

但是更加有意义的是,如果计算中使用方法得当,分区表参与计算的时候能只从指定的分区里读取数据作为输入,从而能减少计算量,缩短计算时间,还能减少费用。以下是一个典型的例子:ods_oplog表里有我模拟的2天(20161113、20161114)的日志(一共5条),ds作为分区。假如我的这次计算只需要20161113的数据,我们可以用sql:

MaxCompute的分区配置和使用

从这个sql的执行计划和最后的结果来看,虽然表里有2个分区,但是因为使用了where ds='20161113',所以查询的时候只用到了ds='20161113'一个分区的数据,剩下的数据没有做为input参与计算。

目前还有一个问题,如果查询只根据二级分区进行过滤,因为没有指定一级分区所以会扫描所有一级分区,也一样可能会出现这个错误。

关于sql里查询条件怎么使用到分区带来的好处,前面的分区的例子其实已经提到了。只是需要注意的是,目前分区列需要是string类型,所以sql里要写成ds='20161113'不要写成ds=20161113以避免自动类型转换后得到预期外的结果。

对于分区表,数据写入的时候需要指定数据写入的分区,用文档里的例子:

再对应到前面提到的文件和目录的说法,因为数据的目录不存放具体的数据,只需要指定数据具体写到哪个目录后,把普通列的数据select出来后写入到表里就可以了。

但是确实有一些场景,需要把查询结果,根据某个字段的值,智能得写入到对应的分区里,那就需要用到动态分区,具体的语法可以参考

在java里,分区的对应的就是com.aliyun.odps.partitionspec了。这个类有2个构造,除了无参构造,还有一个传入字符串的。

这是一个实际使用,需要传入partitionspec 的例子(使用sdk创建一个新的分区)