云原生主键模型:高效、弹性,省钱又省心

作者简介:罗一鑫,StarRocks Committer,主要负责存储引擎相关的工作。

导读:

在 StarRocks 3.3.1 版本中,我们推出了云原生持久化索引,旨在解决本地磁盘持久化索引的关键问题。本文将详细探讨其优势,并对比云原生与本地磁盘持久化索引在大批量导入、小批实时导入以及弹性调度等场景中的表现。尤其在弹性调度场景中,云原生架构使延迟性能提升至本地磁盘的 10 倍。

主键模型是 StarRocks 全新设计开发的存储引擎,其主要优势在于支撑实时数据更新的同时,也能保证高效的复杂即席查询性能。通过主键表,实时分析业务能够在最新数据上进行分析,从而实现及时决策,突破了传统 T+1 数据延迟的限制。主键表中的主键具备唯一非空约束,用于唯一标识每一行数据。如果新数据的主键值与表中原数据的主键值相同,则存在唯一约束冲突,新数据将替代原有数据。

从 StarRocks 3.1 版本开始,主键模型开始支持存算分离架构的部署模式。在主键模型的实现中,主键索引是其核心组件。主键索引保存了从主键与对应数据位置的映射关系,从而可以帮助我们实现:

  1. 在 upsert/delete 操作中对旧数据的快速标记删除

  2. 部分列更新

  3. 高并发点查加速

  4. ......

在之前的版本中,存算分离架构下支持了两类主键索引实现:

  1. 内存索引

  2. 基于本地磁盘的持久化索引

内存索引由于大量占用内存资源,目前已不推荐使用,默认转为基于本地磁盘的持久化索引。虽然持久化索引显著降低了内存开销,并提供强劲的性能,但在云原生场景下仍存在以下问题:

  1. 磁盘空间的使用与 local data cache 管理不统一,可能导致磁盘空间抢占问题。

  2. 扩缩容不够灵活。调度迁移后的 tablet,需要在新节点上重建索引,耗时长,影响实时数据导入。

  3. Compute Node 节点需挂载足够大的本地磁盘。

引入云原生持久化索引

为了解决本地磁盘的持久化索引存在的问题,从 StarRocks 3.3.1 版本开始,我们推出了云原生持久化索引,其主要优势包括:

  1. 索引文件存储在对象存储上,通过和数据文件一致的 local data cache 来做访问加速,实现缓存统一管理。

  2. 支持弹性扩缩容。调度迁移后的 tablet 只需拉取少量数据即可完成索引重建,不影响导入的实时性。

  3. 不再要求 Compute Node 节点挂载本地磁盘,减少了对磁盘空间的硬性要求,进一步降低了硬件成本。

导入性能对比

为了评估云原生持久化索引的实际性能提升,我们对比了云原生持久化索引与本地磁盘持久化索引在以下几种场景中的表现:

  1. TPCH100G 数据批量导入

  2. 订单表小批实时导入

  3. 弹性调度测试

通过对这些场景的性能测试,我们将详细分析云原生持久化索引在延迟性能上的显著提升,以及在实际应用中的优势。

测试环境

1 FE : ecs.g6.xlarge (4c 16g) - PL0
1 BE : ecs.g6.4xlarge (16c 64g) - PL1

对比版本

Version: branch-3.3-2b87854

测试场景

TPC-H 100G 数据批量导入

建表语句:

CREATE TABLE `lineitem_pk` (
  `l_shipdate` date NOT NULL COMMENT "",
  `l_orderkey` int(11) NOT NULL COMMENT "",
  `l_linenumber` int(11) NOT NULL COMMENT "",
  `l_partkey` int(11) NOT NULL COMMENT "",
  `l_suppkey` int(11) NOT NULL COMMENT "",
  `l_quantity` decimal(15, 2) NOT NULL COMMENT "",
  `l_extendedprice` decimal(15, 2) NOT NULL COMMENT "",
  `l_discount` decimal(15, 2) NOT NULL COMMENT "",
  `l_tax` decimal(15, 2) NOT NULL COMMENT "",
  `l_returnflag` varchar(1) NOT NULL COMMENT "",
  `l_linestatus` varchar(1) NOT NULL COMMENT "",
  `l_commitdate` date NOT NULL COMMENT "",
  `l_receiptdate` date NOT NULL COMMENT "",
  `l_shipinstruct` varchar(25) NOT NULL COMMENT "",
  `l_shipmode` varchar(10) NOT NULL COMMENT "",
  `l_comment` varchar(44) NOT NULL COMMENT ""
) ENGINE=OLAP
PRIMARY KEY(`l_shipdate`, `l_orderkey`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96
PROPERTIES (
"compression" = "LZ4",
"datacache.enable" = "true",
"enable_async_write_back" = "false",
"replication_num" = "1",
"storage_volume" = "builtin_storage_volume",
"enable_persistent_index" = "true",
"persistent_index_type" = "LOCAL|CLOUD_NATIVE"
);


CREATE TABLE `orders_pk` (
  `o_orderkey` int(11) NOT NULL COMMENT "",
  `o_orderdate` date NOT NULL COMMENT "",
  `o_custkey` int(11) NOT NULL COMMENT "",
  `o_orderstatus` varchar(1) NOT NULL COMMENT "",
  `o_totalprice` decimal(15, 2) NOT NULL COMMENT "",
  `o_orderpriority` varchar(15) NOT NULL COMMENT "",
  `o_clerk` varchar(15) NOT NULL COMMENT "",
  `o_shippriority` int(11) NOT NULL COMMENT "",
  `o_comment` varchar(79) NOT NULL COMMENT ""
) ENGINE=OLAP
PRIMARY KEY(`o_orderkey`, `o_orderdate`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96
PROPERTIES (
"compression" = "LZ4",
"datacache.enable" = "true",
"enable_async_write_back" = "false",
"replication_num" = "1",
"storage_volume" = "builtin_storage_volume",
"enable_persistent_index" = "true",
"persistent_index_type" = "LOCAL|CLOUD_NATIVE"
);

导入语句:

insert into lineitem_pk select * from lineitem;
insert into orders_pk select * from orders;

导入结果:

图片

订单表小批实时导入

建表语句:

CREATE TABLE tbl_pk (
  `lo_orderkey` string,
  `lo_linenumber` int(11),
  `lo_custkey` int(11),
  `lo_partkey` int(11),
  `lo_suppkey` int(11),
  `lo_orderdate` varchar(15),
  `lo_orderpriority` varchar(16),
  `lo_shippriority` int(11),
  `lo_quantity` int(11),
  `lo_extendedprice` int(11),
  `lo_ordtotalprice` int(11),
  `lo_discount` int(11),
  `lo_revenue` int(11),
  `lo_supplycost` int(11),
  `lo_tax` int(11),
  `lo_commitdate` bigint(11),
  `lo_shipmode` varchar(11)
)
PRIMARY KEY(lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate)
COMMENT "OLAP"
DISTRIBUTED BY HASH(lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate) BUCKETS 6
PROPERTIES (
"replication_num" = "1",
"enable_persistent_index" = "true",
"persistent_index_type" = "LOCAL|CLOUD_NATIVE"
);

导入语句:

curl --location-trusted -u root: -T .../fake_data$loop_file.csv -XPUT -H label:stream_load_$uuid -H "timeout:86400" -H "max_filter_ratio:0.1" http://$host_ip:$http_port/api/$database_name/tbl_pk/_stream_load

导入数据为大小7.6G随机生成的订单数据,切分为100个文件,分100次导入。

导入结果:

图片

弹性调度测试

建表语句:

CREATE TABLE tbl_pk (
  `lo_orderkey` string,
  `lo_linenumber` int(11),
  `lo_custkey` int(11),
  `lo_partkey` int(11),
  `lo_suppkey` int(11),
  `lo_orderdate` varchar(15),
  `lo_orderpriority` varchar(16),
  `lo_shippriority` int(11),
  `lo_quantity` int(11),
  `lo_extendedprice` int(11),
  `lo_ordtotalprice` int(11),
  `lo_discount` int(11),
  `lo_revenue` int(11),
  `lo_supplycost` int(11),
  `lo_tax` int(11),
  `lo_commitdate` bigint(11),
  `lo_shipmode` varchar(11)
)
PRIMARY KEY(lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate)
COMMENT "OLAP"
DISTRIBUTED BY HASH(lo_orderkey,lo_linenumber,lo_custkey,lo_partkey,lo_suppkey,lo_orderdate) BUCKETS 1
PROPERTIES (
"replication_num" = "1",
"enable_persistent_index" = "true",
"persistent_index_type" = "LOCAL|CLOUD_NATIVE"
);

测试过程:

  1. 首先导入数据。

  2. 停止 BE 节点,清理磁盘中的持久化索引文件和缓存,以模拟扩缩容调度后 tablet 被调度到新节点上的情况。

  3. 发起新的导入事务,该事务的耗时中会包含重建索引的时间。通过对比该事务的延迟,验证云原生索引的弹性。

测试结果:

图片

总结分析

  1. 无论是大批导入或是小批实时导入,云原生主键索引性能与本地磁盘索引性能基本持平。

  2. 在弹性调度场景中,得益于云原生的架构,云原生持久化索引的延迟性能提升达到了本地磁盘持久化索引的 10 倍。

如何使用

从 StarRocks 3.3.1 版本开始,我们支持了云原生持久化索引。要启用该功能,可以在建表语句中通过指定 persistent_index_type 为 CLOUD_NATIVE。例如:

CREATE TABLE `orders` (
  `o_orderkey` int(11) NOT NULL COMMENT "",
  `o_orderdate` date NOT NULL COMMENT "",
  `o_custkey` int(11) NOT NULL COMMENT "",
   ...
) ENGINE=OLAP
PRIMARY KEY(`o_orderkey`, `o_orderdate`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96
PROPERTIES (
"enable_persistent_index" = "true",
"persistent_index_type" = "CLOUD_NATIVE" // LOCAL | CLOUD_NATIVE
);

LOCAL

为本地磁盘主键索引(目前默认使用)。

CLOUD_NATIVE

为云原生主键索引。

建表完成后,可以通过show create table语句来确认云原生索引是否成功开启。

目前暂时不支持通过 alter table 语句来动态调整持久化索引的实现类型。

如果您当前正在使用存算分离的主键模型表,并且受到本地磁盘持久化索引的几大缺陷困扰,欢迎尝试新发布的云原生主键索引。虽然云原生主键索引仍处于早期版本,许多实现仍有提升空间,我们将持续优化和改进。您的使用反馈对我们至关重要,欢迎随时提供意见和建议,让我们一起做得更好!

点击下方链接,添加小助手,加入存算分离技术交流:
StarRocks

  • 20
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值