作者:罗一鑫,StarRocks Committer,主要负责存储引擎相关的工作。
导读:
在 StarRocks 3.3.1 版本中,我们推出了云原生持久化索引,旨在解决本地磁盘持久化索引的关键问题。本文将详细探讨其优势,并对比云原生与本地磁盘持久化索引在大批量导入、小批实时导入以及弹性调度等场景中的表现。尤其在弹性调度场景中,云原生架构使延迟性能提升至本地磁盘的 10 倍。
从 StarRocks 3.1 版本开始,主键模型开始支持存算分离架构的部署模式。在主键模型的实现中,主键索引是其核心组件。主键索引保存了从主键与对应数据位置的映射关系,从而可以帮助我们实现:
在 upsert/delete 操作中对旧数据的快速标记删除 部分列更新 高并发点查加速 ......
在之前的版本中,存算分离架构下支持了两类主键索引实现:
内存索引 基于本地磁盘的持久化索引
磁盘空间的使用与 local data cache 管理不统一,可能导致磁盘空间抢占问题。 扩缩容不够灵活。调度迁移后的 tablet,需要在新节点上重建索引,耗时长,影响实时数据导入。 Compute Node 节点需挂载足够大的本地磁盘。
为了解决本地磁盘的持久化索引存在的问题,从 StarRocks 3.3.1 版本开始,我们推出了云原生持久化索引,其主要优势包括:
索引文件存储在对象存储上,通过和数据文件一致的 local data cache 来做访问加速,实现缓存统一管理。 支持弹性扩缩容。调度迁移后的 tablet 只需拉取少量数据即可完成索引重建,不影响导入的实时性。 不再要求 Compute Node 节点挂载本地磁盘,减少了对磁盘空间的硬性要求,进一步降低了硬件成本。
为了评估云原生持久化索引的实际性能提升,我们对比了云原生持久化索引与本地磁盘持久化索引在以下几种场景中的表现:
TPCH100G 数据批量导入 订单表小批实时导入 弹性调度测试
通过对这些场景的性能测试,我们将详细分析云原生持久化索引在延迟性能上的显著提升,以及在实际应用中的优势。
测试环境
测试环境
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
导入结果:
弹性调度测试
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"
);
首先导入数据。
停止 BE 节点,清理磁盘中的持久化索引文件和缓存,以模拟扩缩容调度后 tablet 被调度到新节点上的情况。
发起新的导入事务,该事务的耗时中会包含重建索引的时间。通过对比该事务的延迟,验证云原生索引的弹性。
总结分析
总结分析
无论是大批导入或是小批实时导入,云原生主键索引性能与本地磁盘索引性能基本持平。
在弹性调度场景中,得益于云原生的架构,云原生持久化索引的延迟性能提升达到了本地磁盘持久化索引的 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
Linux 基金会项目 StarRocks 是新一代极速全场景 MPP 数据库,遵循 Apache 2.0 开源协议。
StarRocks 全球开源社区也正飞速成长。目前,StarRocks 的 GitHub star 数已达 8500,吸引了超过 350 位贡献者和数十家国内外行业头部企业参与共建,用户社区也有过万人的规模。凭借其卓越的表现,StarRocks 荣获了全球著名科技媒体 InfoWorld 颁发的 2023 BOSSIE Award 最佳开源软件奖项。