本文档主要介绍了分区投影功能的背景信息、使用场景和限制,以及如何使用分区投影功能。

背景信息

当您把数据存储在OSS或HDFS上,并建立大量的分区管理这些数据。DLA Presto在分析这些数据时,会花费大量的时间从元数据系统中获取分区,从而影响查询性能。通过使用分区投影功能,根据表的配置DLA Presto可以直接计算得出分区值和分区位置,避免从元数据系统中获取分区,从而减少针对大量分区表的查询运行时间。分区投影

使用场景

如果您的数据存在以下场景,建议您使用分区投影功能:
  • 如果您的表使用了大量的分区,DLA Presto从元数据系统中获取分区需要花费大量的时间。
  • 如果您的表每天都会增加一个分区(比如 dt=2021-02-19),而您不想每天都去手动添加分区。
  • 如果您的数据存储在OSS中,里面建有大量的分区(比如几万个),但是您只需要查询其中的一小部分分区。

限制说明

  • 启用分区投影的表存在以下SQL命令限制:
    • 不能使用MSCK REPAIR TABLE tblNameALTER TABLE tblName ADD PARTITION来添加分区。
    • 不能使用SHOW PARTITIONS tblName来查看分区。
    • 不能使用ALTER TABLE tblName DROP PARTITION来删除分区。
  • 分区投影当前仅支持DLA的Presto计算引擎,并且只能在Presto引擎的CU版本中使用。
  • 当分区路径在OSS中不存在时,使用分区投影功能执行SQL,DLA会返回空的结果,不会进行报错。

如何使用分区投影

分区投影属于表级别的功能,您只需要在建表的时候指定相关属性即可。启用分区投影功能的建表示例如下:
create external table projection_test (
  field1 int
) 
partitioned by (
  a string, 
  b string, 
  c int, 
  d string
) 
LOCATION 'oss://oss-cn-hangzhou-xxx/xxx/projection_test' 
tblproperties(
  'projection.enabled' = 'true',    #projection.enabled设置为true,表示为这个表开启分区投影功能。
  'projection.a.type' = 'injected',
  'projection.a.miss' = 'LIST',
  'projection.b.type' = 'date',
  'projection.b.range' = '2021-02-01, NOW',
  'projection.b.format' = 'yyyy-MM-dd',
  'projection.b.interval.unit' = 'days',  
  'projection.b.interval' = '1',
  'projection.c.type' = 'integer',   #projection.columnName.type(projection.c.type)表示列的分区投影类型,具体请参见下文《分区投影类型》。
  'projection.c.range' = '1,2',
  'projection.d.type' = 'enum',
  'projection.d.values' = '1,2',
  'storage.location.template' = 'oss://oss-cn-hangzhou-xxx/xxx/projection_test/${a}/${b}/${c}/${d}/'   #表示分区目录的格式,是一个以分区列作为占位符的路径模板。默认的格式为table_path/分区列名1=取值1/分区列名2=取值2/...,也可以指定为其他格式。
)

分区投影类型

projection.c.type表示列的分区投影类型。目前DLA支持四种分区投影类型:enumintegerdate以及injected。不同类型需要设置不同的投影参数,如下表所示:
  • 枚举类型(enum)
    属性名称 是否必填 示例值 描述
    projection.columnName.type enum 表示分区列是枚举类型。
    projection.columnName.values RED, YELLOW, GREEN 使用英文逗号分隔的枚举值。
  • 整数类型(integer)
    属性名称 是否必填 示例值 描述
    projection.columnName.type integer 表示分区列是整数类型。
    projection.columnName.range 1, 100, -666, 8888 使用英文逗号分隔的整数,可以为负数。用逗号分隔的第一个数必须比第二个数小。
    projection.columnName.interval 1 代表分区列的连续分区值之间的间隔。必须是一个大于0的整数,默认值为1。例如:projection.columnName.range=1,10、projection.columnName.interval=3,则生成的分区值为1,4,7。
    projection.columnName.digits 1 为最后生成的分区进行格式化。必须是一个正整数,默认为0。例如:projection.columnName.range =1,10、projection.columnName.interval=3、projection.columnName.digits=2,则生成的分区值为01,04,07。
  • 日期类型(date)
    属性名称 是否必填 示例值 描述
    projection.columnName.type date 表示分区列是日期类型。
    projection.columnName.range 20201212, 20210219, 2020-12,NOW-8YEARS, NOW+6months 使用英文逗号分隔的日期值。可以是正常的字符串日期,例如:2021-02-19,也可以使用NOW、+/-、YEARS、MONTHS、WEEKS、DAYS、HOURS、MINUTES、SECONDS组成的字符串,但必须符合\s*NOW\s*(([\+\-])\s*([0-9]+)\s*(YEARS?|MONTHS?|WEEKS?|DAYS?|HOURS?|MINUTES?|SECONDS?)\s*)? 正则表达式,不区分大小写。
    projection.columnName.format yyyy-MM, yyyy/MM/dd, yyyyMMdd HH:mm:ss 日期的格式,必须能够使用java.text.SimpleDateFormat去解析。
    projection.columnName.interval 1 代表分区列的连续分区值之间的间隔。必须是一个大于0的整数,默认值为1。
    projection.columnName.interval.unit YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS 代表日期的增长单位,支持左表的值,不区分大小写。例如:projection.columnName.range=2020-02, 2021-02,而projection.columnName.interval=3, projection.columnName.interval.unit= months,则生成的分区值为2020-02, 2020-05, 2020-08, 2020-11, 2021-02。
  • 注入类型(injected)
    属性名称 是否必填 示例值 描述
    projection.columnName.type injected 表示分区列是注入类型。取值范围不受限制。
    projection.columnName.miss ERROR 取值:ERROR或LIST,不区分大小写。
    • ERROR:表示查询没有指定这个分区列就报错。
    • LIST:表示查询如果没有指定这个分区列,就从文件系统OSS里面list出分区所在的目录,把符合结构的目录都作为一个分区来处理。
      注意 LIST行为可能对性能有一定影响,请谨慎使用。
    说明 如果projection.columnName.miss=LIST,从OSS中list出来的目录大于1000个,DLA Presto会花费大量的时间从OSS获取数据,查询会报错。您可以在查询的时候通过指定hintprojection-max-paths=-1来避免查询报错。如下:
    /*+ projection-max-paths=-1 */ select * from projection_test;