【进入 OLAP 领域的入场券】列存引擎

我们针对 OceanBase 4.3 版本的列存功能,写了一篇偏用户向的博客,包括了列存的适用场景、基础语法,以及使用建议,并在博客中最后的 “问答记录” 部分记录了各位读者对文章内容的疑问和解答。博客链接:《进入 OLAP 领域的入场券 —— 列存引擎》

大家如果还希望了解列存的哪些点,或者对这篇博客有哪些建议,都可以直接在这个帖子下面评论,以便我们后面产出更多能够帮助到大家的文档。

12 个赞

就看到了这,还没看完,想到问题就随时提问了 :smiling_imp:

在 OceanBase 4.3 版本中创建表时,可以选择把表创建成行存表、列存表、行列冗余存储的表。无论是什么模式的表,表的增量数据均保持行存格式,因此列存表的 DML、事务、上下游数据同步都不会受到影响。

此处,对已经存在的行存表、列存表支持alter table添加改成行列冗余存储的表吗?
对行列冗余存储的表支持删除行存或者列存吗?

9 个赞

问题2:

在这种行存列存冗余的模式下,优化器会根据访问行存和访问列存的代价高低,自动选择扫描列存 SSTable 还是行存 SSTable。

此处,对于行列冗余的表,支持用hint指定选择列存还是行存吗?

9 个赞

问题3:

select * from lineitem_column where l_extendedprice = 13059.24;

过滤条件不走宽表的主键和索引时,虽然列存需要拼各个列的结果,这一步会比行存表更耗时。但列存相比行存,可以省下大量的 I / O 开销,行存表在这里是做了一次真正的 “全表扫描”。

此处,列存需要拼各个列的结果,是怎么个拼法?由于是列存,列存中是每一列都存了行的ID么(或者叫key)?不然怎么查到对应的行

9 个赞

支持的,详见博客中的 “行存表和列存表的相互转化” 部分~

10 个赞

支持的,详见博客中的 “列存相关 Hint” 部分~

10 个赞

列存中没有冗余存储主键或者您说的 key,会先根据过滤条件算出结果行的 rowid,然后通过 rowid 去拼各个列存的结果值~

rowid 这个玩意儿还不太好解释,您就简单理解为:提供了快速定位表中某一行能力的,并且不会进行实际存储的这么个东西吧,哈哈~

可以参考下官网文档上 Oracle 模式下对 rowid 伪列的介绍,是类似的~

9 个赞

这篇博客写的太长了,给大家的阅读带来了一些困难,实在不好意思啊…… :joy:

6 个赞

大佬太客气了,我也是没有一口气看完,就看到问题随手发上来了,怕久了或者被其他事情中断就忘了,有问题随时记录。 大佬能随时解答,还是非常感谢的~

7 个赞

这块还是不太明白,如您所说,如果列存中没有存rowid,那是怎么根据一个列的值算出来rowid呢,肯定在一个地方有对应关系的吧 就如这种情况:select * from tab_a where col_1=XXXX;

7 个赞

问题4:

对于列存表来说,如果存在大量更新操作,并且没有及时合并,查询性能是不优的。推荐批量导入数据后发起一次合并,这样可以获得最优的查询性能。

这块,感觉后期会增加对指定表合并的需求。(不知道会不会考虑支持)

问题5:

  • 当查询只需要扫描宽表的单列或者少数列时,列存表可以省下大量的磁盘 I / O 开销。行存宽表为了解决这个问题,需要再特定列上创建索引,让扫描主表的动作变为扫描列数更少的索引。所以列存表相比行存表,可以省下在特定列上创建索引的存储开销和索引的维护开销。

此处,想到个问题,列存中非索引列,合并后的数据是有序的吗?如果更新,在合并是,是否涉及到排序的问题?

6 个赞

哈哈,rowid 可以理解成 sstable 的块号加块内具体某一行的数组下标,访问数据时相当于拿数组下标访问数组的具体某一行,所以不需要额外去存储每一个下标。

解答如何拼列存结果的这个问题,可能会涉及到代码实现,个人感觉不值得用户花太多时间去细究,哈哈~

5 个赞

问题 4:指定具体某张表去进行合并,几个月前内部的测试版本就支持了,当时还试用过一次。但是确切的产品发布时间我还不知道。

问题 5:OB 中的表都是索引组织表,列存中的所有列,无论是不是索引列,都是按照主键序有序的。合并的时候,会按照主键序进行排序。如果是索引列,索引会单独占一份儿存储空间,索引列上的索引会重新按照索引列进行排序,并额外存储主键列,利用主键列和主表进行关联。

6 个赞

这么说就明白了,合并后的数据,不管是行存还是列存,并不会根据列的值去排序,也明白您说的根据过滤条件算出rowid的意思了。

那么新的问题又来了,对一个既有行存,又有列存的表,他的主键是怎么个生成规则,行列混存的索引组织表(聚簇表),是怎么同时支持行和列的查找的(根据主键查找到相关行,列的值)?有相关的文章或者文档介绍么?

3 个赞

标题都很赞 :+1:

4 个赞

没太理解您的这个新问题,OB 的无主键表也有隐藏主键,无论行存还是列存,都可以在任意表中使用主键的。您是在问无主键表的隐藏主键生成规则吗?

如果是的话,可以参考下这篇学习笔记中的一段文字。

下面这条 SQL 里查出来的无主键表的隐藏列 __pk_increment 就是生成的隐藏主键列,官网文档上说是个分区级的自增列(看名字好像也是个自增列)。

create table test(c1 int);

select t.table_name, c.column_name, c. column_id 
    from oceanbase.__all_table t, oceanbase.__all_column c 
    where t.table_id = c.table_id and table_name = 'test';
+------------+----------------+-----------+
| table_name | column_name    | column_id |
+------------+----------------+-----------+
| test       | c1             |        16 |
| test       | __pk_increment |         1 |
+------------+----------------+-----------+
2 rows in set (0.041 sec)
3 个赞

抱歉前面描述的不清楚

这么说吧,行列混存的表,主键是用的两份数据么,一份用行存,给行存用的,另一份是列存,给列存用的,
还是说用的一份,同时供行存和列存使用?

3 个赞

哦哦,理解您的问题了。行列冗余存储的表,在 sstable 中,行存存了一份儿完整的表数据,列存也存了一份儿完整的表数据,所以不仅是主键列,每个列都会冗余存储两遍。生成计划的时候,优化器会根据代价确定好用行存还是用列存,不会混在一起用。

相关的文章有:《OceanBase v4.3 特性解读:查询性能提升之利器列存储引擎》《OceanBase 列存的现在与未来》,这两篇分别是列存研发负责人和存储团队负责人写的,比我那篇博客质量高很多~

5 个赞

多谢大佬,你的文章也很实用,质量也高

拜读一下

3 个赞

速速码住:golf:

3 个赞