OceanBase为什么要有宏块和微块这两级结构?

我们知道,传统单机数据库不论是Oracle、MySql、PostgreSql还是SqlServer,它们的存储引擎都是基于Btree的,在Btree中IO的基本单位是Page,Page的长度可以配置,但一般都是定长的,比如说8KB、16KB这样的大小,一旦配置好就不是太好做调整了。定长的最大好处是方便做磁盘管理,不需要处理碎片的问题,但缺点是数据不好做压缩,这也很好理解,就算数据之前是定长的,一压也就成变长的了。
而一些基于LSM Tree的存储引擎,比如OceanBase和Rocksdb,把数据分为SSTable和MemTable,SSTable是静态只读的,非常适合压缩,所以这也是为什么和Oracle/MySql相比,存储相同的数据量OceanBase要消耗的磁盘空间要少得多。
压缩为用户节省了存储成本,但也带来了磁盘空间管理的问题,OceanBase为了在空间管理和数据压缩之间做平衡,才有了宏块-微块的两层管理结构,宏块大小是定长的,长度为2MB,方便做磁盘管理,是数据写的基本单位;宏块内部包含若干个微块,微块大小是变长的,大小可以4KB-512KB不等,方便做压缩,是数据读的最小单位。一般来说微块大小越大,压缩率越高,但相应一次读IO的代价也越大;微块大小越小,压缩率越低,但相应一次读IO的代价也越小。OceanBase默认的微块大小是16KB(当然实际压缩后是变长的,16KB是个大概建议值),基本上能适用大多数的场景了。

2 个赞

宏块是数据文件写 IO 的基本单位,一个 SSTable 就由若干个宏块构成。在宏块内部数据被组织为多个大小为 16KB 左右的变长数据块,称之为微块(Micro Block),微块中包含若干数据行(Row),微块是数据文件读 IO 的最小单位。宏块是定长的,大小为固定的 2MB,长度不可以被调整;微块是变长的,默认值为 16KB,指的是数据被压缩前的大小.。

那请教下,微块在kvcache中的内存布局是怎么组织的?因为我看缓存全部命中后执行效率很快,比传统行存的快不少。
测试如下:

obclient [tpch]> select sum(L_QUANTITY) from lineitem where L_SHIPINSTRUCT != '';
+-----------------+
| sum(L_QUANTITY) |
+-----------------+
|   1529738036.00 |
+-----------------+
1 row in set (1.569 sec)

obclient [tpch]> select QUERY_SQL,EXECUTE_TIME,MEMSTORE_READ_ROW_COUNT,SSSTORE_READ_ROW_COUNT,DATA_BLOCK_READ_CNT,DATA_BLOCK_CACHE_HIT,INDEX_BLOCK_READ_CNT,INDEX_BLOCK_CACHE_HIT,BLOCKSCAN_BLOCK_CNT,BLOCKSCAN_ROW_CNT,PUSHDOWN_STORAGE_FILTER_ROW_CNT from oceanbase.gv$ob_sql_audit where trace_id in (select last_trace_id() from dual) \G
*************************** 1. row ***************************
                      QUERY_SQL: select sum(L_QUANTITY) from lineitem where L_SHIPINSTRUCT != ''
                   EXECUTE_TIME: 1567588
        MEMSTORE_READ_ROW_COUNT: 0
         SSSTORE_READ_ROW_COUNT: 59986052
            DATA_BLOCK_READ_CNT: 268196
           DATA_BLOCK_CACHE_HIT: 268196
           INDEX_BLOCK_READ_CNT: 1044
          INDEX_BLOCK_CACHE_HIT: 1043
            BLOCKSCAN_BLOCK_CNT: 268195
              BLOCKSCAN_ROW_CNT: 59985920
PUSHDOWN_STORAGE_FILTER_ROW_CNT: 59985920
1 row in set (0.012 sec)

--数据量是5千多万
obclient [tpch]> select count(*) from lineitem;
+----------+
| count(*) |
+----------+
| 59986052 |
+----------+
1 row in set (0.001 sec)

所以有没有关于微块在kvcache中的组织形式以及如何扫描的文章可以share下?

这里有对OB cache结构的一些简单介绍
https://open.oceanbase.com/blog/10900379

请教一下,SST 宏块 微块 相比于经典的 LSM-tree 结构而言,比如 RocksDB 中的 SST 和 data block,OB 的三层结构到底有什么实际的优势呢? 还是不太理解为什么需要这样设计呢?