网站开发要什么,阿里云二级域名建设网站,wordpress 视,个人简介网页制作在涉及大规模数据的复杂分析或即时查询时#xff0c;列式存储是支撑业务负载的关键技术之一。相较于传统的行式存储#xff0c;列式存储采用了不同的数据文件组织方式#xff0c;它将表中的数据以列为单位进行物理排列。这种存储模式允许在分析过程中#xff0c;查询计算仅…在涉及大规模数据的复杂分析或即时查询时列式存储是支撑业务负载的关键技术之一。相较于传统的行式存储列式存储采用了不同的数据文件组织方式它将表中的数据以列为单位进行物理排列。这种存储模式允许在分析过程中查询计算仅需针对所需的列数据进行扫描从而避免了不必要的整行扫描显著降低了IO和内存等资源的消耗进而提升了计算效率。此外列式存储天然具备更佳的数据压缩优势能够实现较高的压缩比有效节约了存储空间并降低了网络传输带宽的占用。
常见的列存存储引擎在实现上往往假设不会有大量随机更新, 尽量保证列存组织数据是静态的。当真正伴随大量数据随机更新时也会不可避免的存在系统性能问题。OceanBase LSM-Tree 架构可以将基线数据和增量数据分别处理正好可以解决这一场景问题。因此 OceanBase 4.3 版本基于当前架构基础进行扩展正式推出列存引擎在一个架构、一个数据库上实现了列存和行存数据存储一体化兼顾 TP 和 AP 查询性能。
为了让有分析诉求的用户顺畅使用新版本围绕列存引擎从优化器到执行器、从 DDL 到事务处理等多模块都进行了适配优化。包括基于列存的新的代价模型和向量化引擎查询下压功能的扩展和增强Skip Index新的列式编码算法自适应 Compaction 等。本文将深入探讨 OceanBase 4.3 版本带来的列存能力、应用场景以及用户关心的未来发展规划。
一、列存整体架构
OceanBase 作为原生分布式数据库默认情况下会为用户数据创建多个副本。为了充分利用多副本的优势为用户提供数据强校验和数据迁移重用等增强体验OceanBase 自研的 LSM-Tree 存储引擎做了深度优化
○ 基线数据相较于业内常见的 LSM-Tree 实现逻辑OceanBase 提出了每日合并的概念。用户可定期或根据操作选择一个全局版本号所有副本的租户数据将在这个版本上进行一轮 Major Compaction生成这个版本的基线数据。所有副本在同一版本下的基线数据完全一致物理上保持一致。
○ 增量数据相对于基线数据增量数据是指在最新版本的基线数据之后写入的数据。增量数据可以是刚写入Memtable的内存数据也可以是已经转储为SSTable 的磁盘数据。增量数据在每个副本中独立维护不保证一致性并且包含了所有多版本的数据。
基于列存应用场景随机更新量可控的背景OceanBase 4.3 结合自身基线数据和增量数据的特质提出了一套对上层透明的列存实现方式基线数据存储为列存模式增量数据保持行存确保用户所有 DML 操作不受影响上下游同步无缝接入列存表数据仍然可以像行存表一样进行所有事务操作。列存模式下每列数据存储为一个独立 SSTable所有列的 SSTable 组合成为一个虚拟 SSTable 作为用户的列存基线数据。同时用户可根据实际业务诉求在建表环节指定设置基线数据可以支持行存、列存、行存列存冗余三种模式提供更好的灵活性。 OceanBase 4.3 版本中不仅在存储引擎中实现了列存模式更从优化器、执行器以等多维度进行列存的适配优化。用户在迁移到列存模式后基本上不会感受到业务变化能够像使用行存一样享受到列存带来的性能优势。列存引擎的全面优化也使得 OceanBase 真正实现了 TP AP 一体化实现了一套引擎、一套代码支持不同类型业务的目标打造更加完善的 HTAP 混合负载实时分析能力。 二、OceanBase 实现列存有哪些天然优势
一成熟的 LSM-Tree 引擎
与传统数据库相比OceanBase 拥有天然的 Delta Store非常适合实现列存。基于 LSM-Tree 存储引擎的支持OceanBase 列存不仅支持完整的事务而且基础算子的性能不弱于传统的 TP 数据库。在列存上完整的事务支持使得 OceanBase 在更新方面具有天然优势所有事物语义和多样事物的管理对用户来说完全透明的用户可以轻松切换到列存模式将列存数据库当成行存数据库使用对业务完全透明不需要做任何改动。
二完善的执行引擎
OceanBase 不仅拥有完整的执行引擎还具备通用的优化器是通用的。在行存模式下OceanBase 已经实现向量化存储引擎的无缝对接无需任何修改即可支持向量化执行。此外OceanBase 实现一套优化器的代码在上层对行存和列存进行不同代价的估算使得用户的 SQL 可以自动选择行存或列存。
三灵活的原生分布式
OceanBase 天然支持分布式并行查询引擎未来还可以轻松扩展到列存异构副本。列存异构副本的优势体现在用户需要完全硬隔离的应用场景中未来的OceanBase 版本将新增这一功能。
综上所述OceanBase 凭借其天然优势推动了 4.3 版本中列存功能的实现。引入列存储引擎后OceanBase 整体架构在外部表现上完全不变并且从架构层面支持了列存相关的三种模式
○ 基线列存 增量行存基线数据采用列存方式存储增量数据采用行存方式存储。
○ 灵活的行存/列存索引可以对行存表建立列存索引也可以对列存表建立行存索引还可以对两者进行任意组合。由于所有列存表和索引的底层存储结构是统一的因此 OceanBase 可以自动支持列存和行存的索引。
○ 列存副本OceanBase 正在研发的列存副本功能。得益于原生分布式能力只需对模式或表做部分修改即可以通过 Compaction 将新增的只读副本转换为列存存储模式。 三、列存使用方法
一默认创建列存表
对于 OLAP 业务需求我们推荐默认创建列存表。如何确保租户创建出来的表默认为列存表只通过下面的配置项即可实现
alter system set default_table_store_format column;
随后我们创建的表格没有指定 column group 时默认创建为列存表。
OceanBase(roottest)create table t1 (c1 int primary key, c2 int ,c3 int);
Query OK,0 rows affected (0.301 sec)OceanBase(roottest)show create table t1;CREATE TABLE t1 (c1 int(11) NOT NULL,c2 int(11) DEFAULT NULL,c3 int(11) DEFAULT NULL,PRIMARY KEY (c1)
) DEFAULT CHARSET utf8mb4 ROW_FORMAT DYNAMIC COMPRESSION zstd_1.3.8 REPLICA_NUM 1 BLOCK_SIZE 16384 USE_BLOOM_FILTER FALSE TABLET_SIZE 134217728 PCTFREE 0
WITH COLUMN GROUP(each column)1 row in set (0.101 sec)
二指定创建列存表
为了方便用户创建列存表列存引入新的语法 with column group当用户建表时最后指定 with column group(each column) 即表示创建列存表。
OceanBase(roottest)create table tt_column_store (c1 int primary key, c2 int ,c3 int) with column group (each column);
Query OK,0 rows affected (0.308 sec)OceanBase(roottest)show create table tt_column_store;CREATE TABLE tt_column_store (c1 int(11) NOT NULL,c2 int(11) DEFAULT NULL,c3 int(11) DEFAULT NULL,PRIMARY KEY (c1)
) DEFAULT CHARSET utf8mb4 ROW_FORMAT DYNAMIC COMPRESSION zstd_1.3.8 REPLICA_NUM 1 BLOCK_SIZE 16384 USE_BLOOM_FILTER FALSE TABLET_SIZE 134217728 PCTFREE 0 WITH COLUMN GROUP(each column)1 row in set (0.108 sec)
三指定创建列存行存冗余表
在某些场景下用户可以容忍一定程度的数据冗余以满足 AP/TP 业务场景的双重需求。此时可以增加行存数据的冗余通过 with column group 语法增加指定 all columns 即可实现。
create table tt_column_row (c1 int primary key, c2 int , c3 int) with column group (all columns, each column);
Query OK, 0 rows affected (0.252 sec)OceanBase(roottest)show create table tt_column_row;
CREATE TABLE tt_column_row (c1 int(11) NOT NULL, c2 int(11) DEFAULT NULL, c3 int(11) DEFAULT NULL, PRIMARY KEY (c1)
) DEFAULT CHARSET utf8mb4 ROW_FORMAT DYNAMIC COMPRESSION zstd_1.3.8 REPLICA_NUM 1 BLOCK_SIZE 16384 USE_BLOOM_FILTER FALSE TABLET_SIZE 134217728 PCTFREE 0 WITH COLUMN GROUP(all columns, each column)1 row in set (0.075 sec)
四列存扫描
如何查看是否列存扫描计划计划展示上新增 COLUMN TABLE FULL SCAN描述列存表的范围扫描。
OceanBase(roottest)explain select * from tt_column_store;
--------------------------------------------------------------------------------------------------------
| Query Plan |
--------------------------------------------------------------------------------------------------------
| |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------------------------- |
| |0 |COLUMN TABLE FULL SCAN|tt_column_store|1 |7 | |
| |
| Outputs filters: |
| ------------------------------------- |
| 0 - output([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), filter(nil), rowset16 |
| access([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), partitions(p0) |
| is_index_backfalse, is_glOceanBaseal_indexfalse, |
| range_key([tt_column_store.c1]), range(MIN ; MAX)always true |
--------------------------------------------------------------------------------------------------------
计划展示上新增 COLUMN TABLE GET描述列存表上的指定主键的 get 操作。
OceanBase(roottest)explain select * from tt_column_store where c1 1;
--------------------------------------------------------------------------------------------------------
| Query Plan |
--------------------------------------------------------------------------------------------------------
| |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------------------- |
| |0 |COLUMN TABLE GET|tt_column_store|1 |14 | |
| |
| Outputs filters: |
| ------------------------------------- |
| 0 - output([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), filter(nil), rowset16 |
| access([tt_column_store.c1], [tt_column_store.c2], [tt_column_store.c3]), partitions(p0) |
| is_index_backfalse, is_global_indexfalse, |
| range_key([tt_column_store.c1]), range[1 ; 1], |
| range_cond([tt_column_store.c1 1]) |
--------------------------------------------------------------------------------------------------------
12 rows in set (0.051 sec)
如何通过 Hint 指定列存行存冗余表走列存扫描对于列存行存冗余表优化器会根据代价选择走行存或者列存扫描如简单场景做全表扫描会默认使用行存生成计划。
OceanBase(roottest)explain select * from tt_column_row;
--------------------------------------------------------------------------------------------------
| Query Plan |
--------------------------------------------------------------------------------------------------
| |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| -------------------------------------------------------- |
| |0 |TABLE FULL SCAN|tt_column_row|1 |3 | |
| |
| Outputs filters: |
| ------------------------------------- |
| 0 - output([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), filter(nil), rowset16 |
| access([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), partitions(p0) |
| is_index_backfalse, is_global_indexfalse, |
| range_key([tt_column_row.c1]), range(MIN ; MAX)always true |
--------------------------------------------------------------------------------------------------
如果用户希望通过手动调优走列存扫描可以通过 hint USE_COLUMN_TABLE 来强制 tt_column_row 表走列存扫描。
OceanBase(roottest)explain select /* USE_COLUMN_TABLE(tt_column_row) */ * from tt_column_row;
--------------------------------------------------------------------------------------------------
| Query Plan |
--------------------------------------------------------------------------------------------------
| |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------------- |
| |0 |COLUMN TABLE FULL SCAN|tt_column_row|1 |7 | |
| |
| Outputs filters: |
| ------------------------------------- |
| 0 - output([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), filter(nil), rowset16 |
| access([tt_column_row.c1], [tt_column_row.c2], [tt_column_row.c3]), partitions(p0) |
| is_index_backfalse, is_global_indexfalse, |
| range_key([tt_column_row.c1]), range(MIN ; MAX)always true |
--------------------------------------------------------------------------------------------------类似的方式通过 Hint NO_USE_COLUMN_TABLE 可以强制表不进行列存扫描。
OceanBase(roottest)explain select /* NO_USE_COLUMN_TABLE(tt_column_row) */ c2 from tt_column_row;
------------------------------------------------------------------
| Query Plan |
------------------------------------------------------------------
| |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| -------------------------------------------------------- |
| |0 |TABLE FULL SCAN|tt_column_row|1 |3 | |
| |
| Outputs filters: |
| ------------------------------------- |
| 0 - output([tt_column_row.c2]), filter(nil), rowset16 |
| access([tt_column_row.c2]), partitions(p0) |
| is_index_backfalse, is_global_indexfalse, |
| range_key([tt_column_row.c1]), range(MIN ; MAX)always true |
------------------------------------------------------------------
11 rows in set (0.053 sec) 四、未来展望
OceanBase 4.3 列存的引入为用户的数据分析以及实时分析场景提供了新的选择。未来OceanBase 列存将持续演进为用户带来更加丰富的 feature、更强劲的性能以及更灵活的部署模式。
第一更丰富的功能。目前我们支持纯列存储引擎未来将实现可自定义的灵活列组组织支持满足不同场景的分析需求。此外我们计划将增量旁路导入功能进一步增强帮助用户实现高效的数据导入缩短数据分析准备时间。
第二更好的性能。增强 Skip Index 的支持使其能够更好地满足用户的查询需求。此外我们计划实现格式一体化目前存储的格式多样化未来将实现存储格式与 SQL 向量化引擎的紧密结合使得在执行 SQL 计算时系统能够识别不同的存储格式从而帮助用户节省更多的数据转换开销。
第三更灵活的部署模式。在未来的版本中我们将支持 OLAP 所需的异构副本以满足用户对强依赖异构副本的需求。此外未来还将支持存算分离模式使得所有用户的 AP 数据库都能够以更低的成本享受存储与计算的分离。