列存即列式存储,是一种将数据按列进行存储和处理的数据管理方式。Lindorm计算引擎支持将半结构化、结构化数据以列存方式进行存储,相较于行式存储,列式存储的查询响应时间更短,消耗IO更少。本文介绍如何通过计算引擎访问Lindorm列存数据。
背景信息
Lindorm列存是面向海量半结构化、结构化数据设计的列格式分布式存储服务,适用于车联网、物联网、订单、日志等大规模存储场景,核心能力包括:
计算分析
Lindorm计算引擎可以访问列存数据,完成海量数据的交互式分析和离线计算。列存提供丰富的索引能力和数据分布特征,可以有效加速计算过程中的数据定位与排布,通过SQL即可完成海量主键数据的增删改查。
高吞吐
列存引擎吞吐能力支持水平扩展,提供每分钟TB级数据的读写能力。适用于车联网数据快速导入、模型训练数据集存取和大规模报表分析生产等高吞吐数据场景。
低成本
通过列格式高压缩比算法、高密度低成本介质、冷热分离、多压缩编码和数据冷归档等技术,Lindorm列存相比自建系统存储成本显著降低,满足海量数据归档留存等低成本存储需求。
高可用
通过纠删码等技术,Lindorm列存保证了分布式数据集的高可用性,同时保证了数据访问无单点。
开源兼容
兼容Iceberg开源标准接口,与Spark、Flink等多种计算引擎互联互通,无缝对接主流数据生态。
冷热分离
您可以根据业务需求将冷热数据存储在不同的介质上,减少访问冷数据带来的性能消耗,同时有效降低存储成本。
前提条件
已阅读使用须知。
根据不同的作业形态,请确保已经完成了以下操作:
JDBC开发实践:JDBC开发实践。
JAR作业开发实践:JAR作业开发实践。
Python作业开发实践:Python作业开发实践。
如果您需要使用冷热分离功能,请确保已开通容量型云存储。具体操作,请参见开通冷存储。
功能说明
DDL
命名空间
表
分区
DML
表
分区整理
在列存分区写入数据,经过一段时间后,您可以执行rewrite_data_files或rewrite_manifest命令,整理分区数据,可以将零散的小文件合并为大文件,减少数据或元数据冗余,提升数据查询性能。详细说明,请参见rewrite_data_files语法和rewrite_manifest语法。
执行rewrite_data_files或rewrite_manifest命令时,会占用数据库资源,建议在业务低峰期执行。
示例一:
USE lindorm_columnar; CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');
示例二:
USE lindorm_columnar; CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');
示例三:
USE lindorm_columnar; CALL lindorm_columnar.system.rewrite_manifest('mydb.mytable');
冷热介质
在数据管理时,为优化成本与性能,通常会选择将高频访问的数据存储在高性能介质上,而对于长时间未访问的历史数据,则希望将其迁移到低成本的存储介质中。Lindorm列存支持三级冷热分层解决方案(从热到冷分别为L1、L2和L3),可以根据业务需求灵活制定列存数据的冷热转换策略。通过数据湖服务自动完成数据在冷热介质之间的自动转储,帮助您有效管理存储成本而不牺牲关键业务的响应速度。
Lindorm列存数据自动冷热转换功能,需联系Lindorm技术支持(钉钉号:s0s3eg3)开通。
参数配置
您可以通过在创建列存表时定义CHS(Cold or Hot Storage)属性,以列存表的时间分区为粒度,定义数据冷热转储。配置CHS的参数说明如下:
参数 | 说明 |
CHS | 配置该参数即表示开启冷热分离,可以配置为:
|
CHS_L1 | 配置L1层选用的存储介质,参数格式为: 说明 如果在创建表时没有配置CHS_L1指定存储介质,则默认使用容量型云存储。 如果您是云存储用户,目标存储类型可选值如下:
如果您是本地盘用户,目标存储类型可选值如下:
|
CHS_L2 | 配置L2层选用的存储介质,参数格式与可选值同CHS_L1。 说明 CHS_L2参数必须配置。 |
CHS_L3 | 配置L3层选用的存储介质,参数格式与可选值同CHS_L1。 说明 如果您的CHS参数为两个长整数时,CHS_L3参数必须配置。 |
CHS_EXP | 配置分区数据时间的提取方法,您需要将其定义为形如: 其中:
Lindorm计算引擎会基于CHS_EXP获取时间分区的最大数据时间,结合CHS中定义的时间阈值范围,将分区数据转储到相应的分层介质。 |
示例
示例一:
创建表
table0
,按年,月,日三个字段分区,字段名称为year,month,day。定义冷热分层策略为:1个月(2592000秒)以前的数据自动转储到容量型云存储。建表语句如下:CREATE TABLE table0 (col0 INT,year STRING,month STRING,day STRING) PARTITIONED BY (year,month) TBLPROPERTIES 'CHS'='2592000', 'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE', 'CHS_EXP'='toSec(year,yyyy,month,MM,day,dd)' );
示例二:
修改
table0
冷热分层策略为:1个月(2592000秒)以前的数据自动转储到容量型云存储,超过3个月(5184000秒)后自动转储到归档型存储,其他规则不变。更新表语句如下:ALTER TABLE table0 SET TBLPROPERTIES ( 'CHS'='2592000,5184000', 'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE', 'CHS_L3'='storagetype=CLOUD_ARCHIVE_STORAGE', 'CHS_EXP'='toSec(year,yyyy,month,MM,day,dd)' );
示例三:
创建
table1
,按天分区,字段名为dt,形如:2020/12/1。定义冷热分层策略为:1个月(2592000秒)以前的数据自动转储到容量型云存储,超过3个月(5184000秒)后自动转储到归档型存储。建表语句如下:CREATE TABLE table1 (col0 INT,dt STRING) PARTITIONED BY (dt) TBLPROPERTIES ( 'CHS'='2592000,5184000', 'CHS_L2'='storagetype=CAPACITY_CLOUD_STORAGE', 'CHS_L3'='storagetype=CLOUD_ARCHIVE_STORAGE', 'CHS_EXP'='toSec(dt,yyyy/MM/dd)' );
注意事项
在创建表时,您可以指定CHS参数。如果后续需要更改冷热分层策略,可以通过执行
ALTER TABLE ...SET TBLPROPERTIES...
语句来调整配置。错误的CHS配置不会影响表创建与更新,但会导致无法自动触发冷热介质转换功能。
数据的冷热转储过程是通过异步方式触发的。在整个转储过程中及完成后,数据访问均不受影响,但基于不同存储介质,访问性能可能会有所变化。
仅支持基于列存表的时间分区来实现数据冷热分层策略,暂不支持其他方式。
最佳实践
您可以通过以下方案,加速数据查询或计算。
主键数据查询
如果表中存储了海量数据集,查询时可以指定通过主键过滤条件,实现加速效果。查询时,主键的数据范围设置得越小,加速效果越好。
假设表结构如下:
USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey INT NOT NULL,
o_custkey INT,
o_orderstatus STRING,
o_totalprice DOUBLE,
o_orderdate STRING,
o_orderpriority STRING,
o_clerk STRING,
o_shippriority INT,
o_comment STRING)
PARTITIONED BY (bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderkey');
示例一:
USE lindorm_columnar; SELECT * FROM orders WHERE o_orderkey=18394;
示例二:
USE lindorm_columnar; SELECT count(*) FROM orders WHERE o_orderkey>100000 AND o_orderkey<200000;
示例三:
USE lindorm_columnar; SELECT count(*) FROM orders WHERE o_orderkey>100000;
添加分区过滤
Lindorm列存引擎中不同分区之间彼此物理隔离,因此,通过添加分区过滤条件,可以加速数据查询。
假设表结构如下:
USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey INT NOT NULL,
o_custkey INT,
o_orderstatus STRING,
o_totalprice DOUBLE,
o_orderdate STRING NOT NULL,
o_orderpriority STRING,
o_clerk STRING,
o_shippriority INT,
o_comment STRING)
PARTITIONED BY (o_orderdate, bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderdate,o_orderkey');
示例一:
USE lindorm_columnar; SELECT o_orderdate, count(*) FROM orders WHERE o_orderdate='2022-01-01' GROUP BY o_orderdate;
示例二:
USE lindorm_columnar; SELECT o_orderdate, count(*) FROM orders WHERE o_orderdate>='2022-01-01' AND o_orderdate<='2022-01-07' GROUP BY o_orderdate;
查询加速
对指定表或者表中的指定分区进行数据整理(Rewrite),可以增强数据的有序性或紧凑性,从而提升数据扫描性能。
假设表结构如下:
CREATE TABLE mydb.mytable (
id INT NOT NULL,
city STRING NOT NULL,
name STRING,
score INT)
partitioned by (city, bucket(4, id))
tblproperties('primary-key' = 'id,city');
示例一:对mydb.mytable全表进行数据整理。
CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable');
示例二:对指定分区进行数据整理。
CALL lindorm_columnar.system.rewrite_data_files(table => 'mydb.mytable', where => 'city=\"beijing\"');
完成数据整理后,如果想要进一步提升后续查询的效率,可以执行以下语句设置表的相关参数来加速后续查询:
ALTER TABLE mydb.mytable SET TBLPROPERTIES ('read.scan-major-rewritten-files-only' = true);
参数说明
read.scan-major-rewritten-files-only:指定数据查询范围。数据类型为BOOLEAN。取值如下:
true:只查询已完成数据整理的数据,忽略增量写入且未完成数据整理的数据。
false:默认值。查询所有数据。
非主键条件查询
针对分区整理过程,列存表默认按主键排序,可以在建表后按需配置排序键,从而加速非主键条件查询。
自定义排序键加速查询效果需要在配置排序键后进行分区整理,且只扫描已进行分区整理的数据,不再扫描增量数据。
假设表结构如下:
USE lindorm_columnar;
CREATE TABLE orders (
o_orderkey INT NOT NULL,
o_custkey INT,
o_orderstatus STRING,
o_totalprice DOUBLE ,
o_orderdate STRING ,
o_orderpriority STRING,
o_clerk STRING,
o_shippriority INT,
o_comment STRING)
PARTITIONED BY (bucket(1024,o_orderkey))
TBLPROPERTIES(
'primary-key' = 'o_orderkey',
'read.scan-major-rewritten-files-only' = 'true');
执行以下语句配置排序键:
ALTER TABLE orders WRITE ORDERED BY o_shippriority,o_totalprice;
执行以下语句整理分区:
CALL lindorm_columnar.system.rewrite_data_files(table => 'orders');
您可以使用以下SQL语句查询已完成分区整理的表中的数据。
示例一:
USE lindorm_columnar; SELECT count(*) FROM orders WHERE o_shippriority=0;
示例二:
USE lindorm_columnar; SELECT count(*) FROM orders WHERE o_shippriority=0 AND o_totalprice>999.9;