MaxCompute分层存储支持标准存储、低频存储和长期存储,默认情况下为标准存储。您可以根据数据的访问频率,将某些表或分区的存储类型设置为低频存储或长期存储,实现数据的冷热分层,以降低数据存储费用。
分层存储类型介绍
存储类型 | 描述 |
标准存储 | 默认存储类型,适用于经常访问数据并对数据进行频繁读写操作的场景。 |
低频存储 | 适用于不需要频繁访问的数据,能够有效降低存储费用。 说明
|
长期存储 |
分层存储计费
适用范围
地域限制:华东1(杭州)、华东2(上海)、华北2(北京)、华北3(张家口)、华北6(乌兰察布)、华南1(深圳)、西南1(成都)、中国香港、华东2金融云、华北2金融云、华南1金融云、新加坡、马来西亚(吉隆坡)、印度尼西亚(雅加达)、日本(东京)、德国(法兰克福)、美国(硅谷)。
当前低频存储和长期存储类型的数据不支持Hologres直接访问。同时Hologres直读MaxCompute时,MaxCompute的表或分区目前不会更新最后访问时间(last_access_time)。因此通过分层存储生命周期设置规则时,用
last_access_time条件配置,可能导致某些仅被Hologres持续读取的表或分区也会命中规则。
设置存储类型
存储类型之间可以相互转换,且修改存储类型不会影响数据访问。
存储类型转换说明如下:
转换过程 | 说明 |
标准存储->低频存储 | 支持手动和自动方式转换,无I/O访问费用,同时不更新表/分区的“数据最后更新时间”和“数据最后访问时间”。 |
标准存储->长期存储 | |
低频存储->长期存储 | 支持手动和自动方式转换,手动切换有I/O访问费,自动切换没有,同时不更新表/分区的“数据最后更新时间”和“数据最后访问时间”。 |
低频存储->标准存储 | 仅支持手动转换,有I/O访问费用,同时更新表/分区的“数据最后更新时间”和“数据最后访问时间”。 |
长期存储->低频存储 | |
长期存储->标准存储 |
手动自定义设置
对于非分区表或分区,直接手动自定义设置为低频存储或长期存储类型,设置后立即生效。
命令格式
ALTER TABLE <TABLE_NAME> [PARTITION(<PARTITION_SPEC>)]
SET <TBLPROPERTIES|PARTITIONPROPERTIES>("storagetier"="standard|lowfrequency|longterm");参数说明
TABLE_NAME:必填,待修改的表或者分区存储类型的表名称。
PARTITION_SPEC:当修改分区存储类型时必填。
TBLPROPERTIES|PARTITIONPROPERTIES:修改表或分区的存储类型,取值说明:
TBLPROPERTIES:修改表的存储类型。
PARTITIONPROPERTIES:修改分区的存储类型。
storagetier:必填,分层存储类型,取值说明:
standard:标准存储,只收取存储费用。
lowfrequency:低频存储,会收取存储费用和低频存储数据访问费用。
longterm:长期存储,会收取存储费用和长期存储数据访问费用。
仅支持对分区表中的分区设置分层存储,不支持对分区表设置分层存储。
使用示例
示例1:设置非分区表的存储类型为低频存储。
ALTER TABLE tablename SET TBLPROPERTIES("storagetier"="lowfrequency");查看表属性,可以通过
StorageTier字段确认当前的存储类型。--查看表属性 DESC extended tablename; ---返回结果如下 +-------------------------------------------------------------------+ | Owner: ALIYUN$mofan_****@test.aliyunid.com | | Project: mf_mc_**** | | TableComment: | +-------------------------------------------------------------------+ | CreateTime: 2021-11-18 15:14:00 | | LastDDLTime: 2023-09-11 14:34:55 | | LastModifiedTime: 2023-09-13 15:02:28 | | LastAccessTime: 2023-09-14 10:50:57 | +-------------------------------------------------------------------+ | InternalTable: YES | Size: 1923683131 | +-------------------------------------------------------------------+ | Native Columns: | +-------------------------------------------------------------------+ | Field| Type| Label |ExtendedLabel| Nullable| DefaultValue|Comment | +-------------------------------------------------------------------+ | empno | bigint | | | true | NULL | | | ename | string | | | true | NULL | | | job | string | | | true | NULL | | | mgr | bigint | | | true | NULL | | | hiredate | datetime | | | true | NULL | | | sal | bigint | | | true | NULL | | | comm | bigint | | | true | NULL | | | deptno | bigint | | | true | NULL | | +-------------------------------------------------------------------+ | Extended Info: | +-------------------------------------------------------------------+ | TableID: 8e0cc78c81ab4ad7af30bff7a8e**** | | IsArchived: false | | PhysicalSize: 5771049393 | | FileNum: 3 | | StoredAs: AliOrc | | CompressionStrategy: normal | | odps.timemachine.retention.days: 1 | | ColdStorageStatus: N/A | | encryption_enable: false | | StorageTier: lowfrequency | | StorageTierLastModifiedTime: 2023-09-11 14:34:55 | +-------------------------------------------------------------------+示例2:设置分区表bank_data_pt相应分区的存储类型为低频存储。
ALTER TABLE bank_data_pt PARTITION (credit='yes') SET PARTITIONPROPERTIES ("storagetier" = 'lowfrequency');查看分区属性,可以通过
StorageTier字段确认当前的存储类型。--查看分区属性 DESC extended bank_data_pt PARTITION(credit='yes'); --返回结果 +------------------------------------------------------------------------------------+ | PartitionSize: 0 | +------------------------------------------------------------------------------------+ | CreateTime: 2024-05-10 10:28:16 | | LastDDLTime: 2024-05-10 10:31:01 | | LastModifiedTime: 2024-05-10 10:28:16 | +------------------------------------------------------------------------------------+ | IsExstore: false | | IsArchived: false | | PhysicalSize: 0 | | FileNum: 0 | | ColdStorageStatus: N/A | | StorageTier: LowFrequency | | StorageTierLastModifiedTime: 2024-05-10 10:31:01 | +------------------------------------------------------------------------------------+
通过生命周期规则自动设置
分层存储的生命周期规则可在项目或分区表两个层级配置,基于该规则触发分层存储类型自动转换。即:
项目级别设置:
设置后,该规则将作为默认规则,应用于项目内所有的非分区表,以及所有未单独设置规则的分区表下的分区。这些表和分区会自动转换为对应的存储类型。
分区表级别设置:
为某个分区表单独设置规则后,该规则的优先级高于项目级别的规则。该表下所有分区满足规则,分区会自动转换为对应的存储类型。
重要限制
规则无法在更细的粒度上进行配置:
不支持为单个非分区表设置独立的规则(其继承项目规则)。
不支持为分区表下的某个特定分区设置独立的规则(其继承所属分区表的规则)。
规则执行
当表或分区的生命周期同时满足长期存储(longterm)规则和低频存储(lowfrequency)规则时,会被优先转换为
longterm。当表或分区的生命周期先满足
lowfrequency规则时,会被转换为lowfrequency,之后再满足longterm规则时,会再次被转换为longterm,此时从lowfrequency变成longterm不会产生lowfrequency的访问费用,计费详情请参见分层存储计费。平台每天定时进行两次规则扫描,因此可能出现表或分区满足条件后无法立即进行设置,会存在一定的延迟。
命令格式
项目级别设置生命周期规则
SETPROJECT odps.table.lifecycle.config=<lifecycle_config_json_string>;也可通过MaxCompute控制台设置,具体如下:
登录MaxCompute控制台,在左上角选择地域。
在左侧导航栏,选择。
在项目管理页面,单击目标项目操作列的管理。
在项目配置页面,选择参数配置页签。
在生命周期配置区域,单击编辑。
配置最近访问配置策略和最近修改配置策略参数。
最近访问配置策略:对应
DaysAfterLastAccessGreaterThan参数。最近修改配置策略:对应
DaysAfterLastModificationGreaterThan参数。
分区表设置生命周期规则
分区表建表时设置:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] <table_name> [PRIMARY KEY (<pk_col_name>, <pk_col_name2>),(<col_name> <data_type> [NOT NULL] [DEFAULT <default_value>] [comment <col_comment>], ...)] PARTITIONED BY (<col_name> <data_type> [comment <col_comment>], ...) tblproperties ('lifecycle_config' = '<lifecycle_config_json_string>') ;分区表修改设置:
ALTER TABLE <TABLE_NAME> SET TBLPROPERTIES ('lifecycle_config' = '<lifecycle_config_json_string>');
查看分区表分层存储生命周期的配置
SHOW CREATE TABLE <table_name>;
参数说明
主要参数说明如下,其余参数信息请参见通用参数。
lifecycle_config_json_string:
当项目级别设置生命周期规则时,定义如下。
{ "TierToLowFrequency": { "DaysAfterLastModificationGreaterThan": <days>, //距离最后修改时间超过xx天 "DaysAfterLastAccessGreaterThan": <days>, //距离最后访问时间超过xx天 }, "TierToLongterm": { "DaysAfterLastModificationGreaterThan": <days>, "DaysAfterLastAccessGreaterThan": <days> } //每个条件为可选条件,多个条件为or的关系 }当分区表设置生命周期规则时,定义如下。
{ \"TierToLowFrequency\": { \"DaysAfterLastModificationGreaterThan\": <days>, //距离最后修改时间超过xx天 \"DaysAfterLastAccessGreaterThan\": <days>, //距离最后访问时间超过xx天 }, \"TierToLongterm\": { \"DaysAfterLastModificationGreaterThan\": <days>, \"DaysAfterLastAccessGreaterThan\": <days> } //每个条件为可选条件,多个条件为or的关系 }TierToLowFrequency:低频存储标识。
TierToLongterm:长期存储标识。
DaysAfterLastModificationGreaterThan:定义距离数据最后修改时间超过多少天后自动设置,对应表或分区的LastModifiedTime。
DaysAfterLastAccessGreaterThan:定义距离数据最后访问时间超过多少天后自动设置,若表或分区的LastAccessTime为空,则:
对于2023年10月01日前创建的表或分区,默认按照UTC+0时区的
2023.10.01 00:00:00时间计算。对于2023年10月01日后新建的表或分区,若数据没被访问过,按照CreateTime时间计算。
使用示例
示例1:项目级别设置生命周期规则。
setproject odps.table.lifecycle.config={"TierToLongterm":{"DaysAfterLastAccessGreaterThan":180},"TierToLowFrequency":{"DaysAfterLastAccessGreaterThan":120}};示例2:取消项目级别生命周期配置。
setproject odps.table.lifecycle.config=;示例3:分区表设置生命周期规则。
--分区表建表时设置 CREATE TABLE lifecycle_part_t (key string) PARTITIONED BY (ds STRING) tblproperties ('lifecycle_config' = '{\"TierToLowFrequency\": {\"DaysAfterLastModificationGreaterThan\": 2,\"DaysAfterLastAccessGreaterThan\": 2},\"TierToLongterm\": {\"DaysAfterLastModificationGreaterThan\": 4,\"DaysAfterLastAccessGreaterThan\": 7}}') ; --分区表修改设置 ALTER TABLE lifecycle_part_t SET tblproperties ('lifecycle_config'='{\"TierToLowFrequency\": {\"DaysAfterLastModificationGreaterThan\": 90,\"DaysAfterLastAccessGreaterThan\": 30},\"TierToLongterm\": {\"DaysAfterLastModificationGreaterThan\": 180,\"DaysAfterLastAccessGreaterThan\": 7}}');示例4:分区表取消分层存储生命周期配置。
ALTER TABLE lifecycle_part_t SET tblproperties ('lifecycle_config'='{}');
分层存储表级数据访问权限控制
表或分区被设置为低频存储或长期存储后,访问数据会产生数据访问费用。
默认情况下,用户只要拥有表的SELECT权限,即可访问该表所有存储类型的数据。MaxCompute支持为低频存储、长期存储提供独立的表级访问权限控制。开启后,SELECT权限仅能访问标准存储数据,访问低频、长期存储数据需要额外授予对应的存储类型权限点,从而避免对冷数据的非预期访问和费用超支。
在查询冷分区时,如果无访问权限时任务会直接报错,对比配置冷分区数据过滤权限的方式,可以避免因静默过滤无权限分区造成计算结果不符合预期的情况。
权限模型
全局开关:租户级开启或关闭,默认关闭。关闭时与用户当前行为完全兼容,即拥有SELECT权限即可访问所有存储类型的数据。
权限控制粒度:表级。对分区表在表级别授权后,对该表下所有分区生效。
鉴权策略:开启开关后,访问低频、长期存储数据需同时具备表的SELECT权限和对应存储类型的访问权限点;访问标准存储数据不受影响。
客体(Object) | 操作(Action) | 说明 | 授权方式 |
Table | ReadLowfrequencyStorage | 读取低频存储(lowfrequency)的表或分区数据。 | ACL、Policy |
Table | ReadLongtermStorage | 读取长期存储(long-term)的表或分区数据。 | ACL、Policy |
权限组合效果
以拥有表SELECT权限的用户为例,开启开关后的访问结果如下:
已具备的权限 | 标准存储数据 | 低频存储数据 | 长期存储数据 |
SELECT | 可访问 | 禁止 | 禁止 |
SELECT + ReadLowfrequencyStorage | 可访问 | 可访问 | 禁止 |
SELECT + ReadLongtermStorage | 可访问 | 禁止 | 可访问 |
SELECT + ReadLowfrequencyStorage + ReadLongtermStorage | 可访问 | 可访问 | 可访问 |
使用限制
开关为租户级,开启后对租户下所有项目、所有已设置为低频或长期存储的表和分区生效。建议先完成存量作业的授权梳理,再开启开关,避免影响正在运行的业务任务。
表Owner、项目Owner(Project Owner)、Schema Owner,以及Super_Administrator、Admin角色的用户默认具备相应权限,无需额外授权,同时可作为授权者为其他用户或角色授权。
权限点仅控制冷数据的读取。如需将表或分区从低频、长期存储转换为标准存储,仍需具备表的ALTER权限。
对于开启了Schema语法的项目(三层模型),执行授权和查询操作前需在会话级开启三层语法开关:
SET odps.namespace.schema=true;。
操作步骤
前提条件
已开启租户级分层存储访问控制开关,操作步骤如下:
登录MaxCompute控制台,在左上角选择地域。
在左侧导航栏,选择 。
在租户属性页签,打开租户级Schema语法开关。
注意:开关开启后,仅拥有SELECT权限的用户将无法访问低频、长期存储的数据。请提前完成权限授予,避免存量任务失败。
步骤一:确认表或分区的存储类型
通过表属性或分区属性中的StorageTier字段确认当前存储类型,仅低频(lowfrequency)、长期(longterm)存储的数据受权限点约束。
-- 查看表属性
DESC EXTENDED <table_name>;
-- 查看分区属性
DESC EXTENDED <table_name> PARTITION(<partition_spec>);步骤二:授予存储类型访问权限
方式一:ACL授权
适用于对单张表精确授权的场景,支持授权给用户或角色。
命令格式
GRANT ReadLowfrequencyStorage|ReadLongtermStorage ON TABLE <table_name> TO USER <user_name>|ROLE <role_name>;参数说明
参数
是否必填
说明
table_name
是
待授权的表名称。分区表在表级别授权后,对该表所有分区生效。
user_name
二选一
被授权的用户。RAM角色用户的格式为
RAM$<账号名称>:role/<RAM角色名称>,使用时需用单引号或反引号包裹。role_name
二选一
被授权的角色。角色需先创建并绑定至目标用户。
使用示例
-- 示例1:授予用户读取低频存储表storage_table_lowfreq的权限。 GRANT ReadLowfrequencyStorage ON TABLE table_name TO USER 'RAM$example:role/data_reader'; -- 示例2:通过角色授予读取权限。 -- 创建角色data_role并绑定至用户。 CREATE ROLE data_role; GRANT data_role TO `RAM$example:role/data_reader`; -- 为角色授予低频存储、长期存储数据的读取权限。 GRANT ReadLowfrequencyStorage ON TABLE table_name TO ROLE data_role; GRANT ReadLongtermStorage ON TABLE table_name TO ROLE data_role;
方式二:Policy授权
适用于批量授权场景,支持通过通配符或正则表达式匹配多张表,仅支持授权给角色。
通过控制台配置
登录MaxCompute控制台,在左上角选择地域。
在左侧导航栏,选择。
在项目管理页面,单击目标项目操作列的管理。
在项目配置页面,单击角色权限页签,为目标角色修改授权。
将授权模型设置为策略(Policy),在文档中填写策略内容后提交。
策略示例:授予角色读取所有以
storage_table_lowfreq开头的表的低频存储数据的权限。{ "Statement": [ { "Action": [ "odps:ReadLowfrequencyStorage" ], "Effect": "Allow", "Resource": [ "acs:odps:*:projects/<project_name>/tables/storage_table_lowfreq*" ] } ], "Version": "1" }
通过SQL命令配置
-- 创建角色data_role并绑定至用户。 CREATE ROLE data_role; GRANT data_role TO `RAM$example:role/data_reader`; -- 允许角色data_role读取所有以storage_table_longterm开头的表的长期存储数据。 GRANT ReadLongtermStorage ON TABLE table_name_* TO ROLE data_role PRIVILEGEPROPERTIES("policy" = "true", "allow" = "true");
步骤三:验证权限
使用被授权账号执行以下命令查看权限是否生效,并访问目标数据进行验证。
-- 查看当前用户的权限,ACL、Policy授权分别显示在对应的Authorization Type中。
SHOW GRANTS;
-- 访问低频存储或长期存储数据。
SELECT * FROM table_name;授权生效后返回查询结果;未授权时报错,错误信息如下:
FAILED: ODPS-0130013:Authorization exception - Authorization failed [4009, 4019], You have no privilege 'odps:ReadLowfrequencyStorage' on {acs:odps:*:projects/<project_name>/tables/<table_name>}常见问题
如何恢复开关开启前的访问行为?
关闭租户级分层存储访问控制开关即可恢复原有行为,即拥有SELECT权限的用户可访问所有存储类型的数据。已授予的权限点不受影响。
分区数据过滤权限
对于已经设置为低频或长期存储的数据,访问时会产生访问费用,基于行级访问控制能力配合GET_PARTITION_META函数可以对低频或长期存储数据进行权限控制,有效控制这些数据的访问。
GET_PARTITION_META
GET_PARTITION_META是一个很特殊的函数,目前只能配合行级权限控制来使用,不能在普通的SQL查询中使用。
语法
struct GET_PARTITION_META(<tableName>, <pt_col1>, <pt_col2>, ..., <pt_col_n>);参数说明
参数名称 | 说明 |
tableName | 表名且必须是分区表,String类型。支持 |
pt_col | 从pt_col1至pt_col_n的每个参数,都对应分区表的一个分区层级。而且每个参数都必须是列引用。 |
返回值说明
返回一个Struct类型,类型为struct<storagetier:string>。Struct只有一个String类型字段,描述对应分区的存储类型。
注意事项
对表增加行级规则时,需要考虑被控制的用户之外的其他用户的访问行为,如果该表之前已经被其他用户访问,则应为这些用户设置明确的规则,以避免因未经预期的禁止访问而导致的数据过滤问题。详情请参见行级访问控制。
默认情况下,MaxCompute的表不仅可以通过SQL进行访问,还支持外部引擎(如Spark、Flink)读取表数据。然而,目前仅MaxCompute SQL引擎支持GET_PARTITION_META函数。因此,如果在行级访问控制中使用了GET_PARTITION_META函数,则该表仅能被MaxCompute SQL引擎读取,其他引擎将无法正常访问该表。
在满足行级权限的前提下,能够访问数据的条件是必须具备数据访问权限控制,即需要拥有该数据的SELECT权限。
GET_PARTITION_META内的过滤条件,不同的场景会有不同的分区裁剪效果。
过滤条件仅涉及到分区表的分区字段。例如允许访问标准存储并且要求第一级分区的取值是
2024。GET_PARTITION_META('storage_table', pt1, pt2).storagetier == 'standard') AND pt1='2024'当使用SQL访问
storage_table,WHERE条件没有分区条件时,系统天然支持分区裁剪,从而避免全表扫描,仅对storage_table中符合要求的分区进行只读访问。过滤条件中包含非分区字段的取值,且使用的是与运算(AND)来连接两个过滤条件。例如允许访问标准存储并且和非分区值
a>100进行与运算(AND)。GET_PARTITION_META('storage_table', pt1, pt2).storagetier == 'standard') AND a > 100当使用SQL访问
storage_table,WHERE条件没有分区条件,依然支持分区裁剪,只访问存储为standard的分区。过滤条件中包含非分区字段的取值,且使用或运算(OR)来连接这两个过滤条件。例如允许访问标准存储并且和非分区值
a>100进行或运算(OR)。get_partition_meta('storage_table', pt1, pt2).storagetier == 'standard') OR a > 100当使用SQL访问
storage_table时,存在两种情形:WHERE没有分区条件,则会访问所有分区以便扫描出满足
a>100的数据。WHERE有分区条件则只扫描对应分区内满足
standard或a>100的数据。
使用示例
定义分区表storage_table。
CREATE TABLE storage_table(a BIGINT, b BIGINT) PARTITIONED BY (pt1 STRING, pt2 STRING);示例一:
为默认用户授予权限
policy01,可以访问storage_table标准存储数据。所有用户(包括Project Owner)不可访问低频或长期存储数据且返回空值。CREATE ROW ACCESS POLICY policy01 ON storage_table TO DEFAULT FILTER USING (get_partition_meta('storage_table', pt1, pt2).storagetier == 'standard');Logview中Summary出现如下关键字则说明触发了行级过滤。
该关键字为
WARNING:[1,15] row access policy is enabled on table yyy_hp_storagetier.storage_table01,表明查询该表时已触发行访问策略。示例二:
授予用户
user_x访问storage_table中低频存储及长期存储数据的权限policy02。CREATE ROW ACCESS POLICY policy02 ON storage_table TO USER (user_x) --也可以通过TO role rolename为角色授权,然后再把角色授权给用户user。 FILTER USING (get_partition_meta('storage_table', pt1, pt2).storagetier IN ('lowfrequency','longterm'));存在以下两种情形:
若表已设置过
policy01权限,所有用户(除user_x外)可以访问storage_table标准存储数据,不可访问低频或长期存储数据,且返回空值。对于user_x用户可访问storage_table的低频和长期存储数据,但不可访问标准存储数据会返回空值。若表未设置过
policy01权限,所有用户(除user_x外)不可访问storage_table任何存储数据且都返回空值。只有user_x用户可访问低频和长期存储数据,但不可访问标准存储数据会返回空值。
示例三:
授予用户
user_y对storage_table所有数据的访问权限policy03。CREATE ROW ACCESS POLICY policy03 ON storage_table TO USER (user_y) --也可以通过TO role rolename为角色授权,然后再把角色授权给用户user。 FILTER USING (true); -- 常量true表示可以访问对应table的所有数据存在以下两种情形:
若表已设置过
policy01权限,所有用户(除user_y外)可以访问storage_table标准存储数据,不可访问低频或长期存储,且返回空值。对于user_y用户可以访问storage_table所有存储类型的数据。若表未设置过
policy01权限,所有用户(除user_y外)不可访问storage_table的任何存储数据且都返回空值。只有user_y用户可访问storage_table所有存储类型数据。