在 OceanBase 中,统计信息有表统计信息(table level statistics)和列统计信息(column level statistics)两种。
表的统计信息主要存储在内部表 __all_meta_table 中,它包含了以下信息:

  • 表的行数

  • 表所占用的微块数

  • 表所占的空间大小

优化器可以利用表统计信息来优化计划的选择。除了非实体表以及统计信息内部表自身以外,所有的表都可以收集表统计信息。
以下是使用表统计信息进行计划选择的一个示例。

  • 列中不同的值的数量(number of distinct values,NDV)

  • 列的最大值最小值

优化器可以利用列的统计信息来优化的选择。除了非实体表以及统计信息内部表自身以外,所有的列都可以收集列统计信息。列的统计信息主要用来计算谓词、连接条件的选择率,从而更好地计算算子向上层吐出的行数。

以下是使用列统计信息来优化查询计划选择的一个例子。

在大多数情况下,表和列的统计信息共同作用,优化器得以利用这些信息更精确地选择执行计划。

此外,由于 OceanBase 底层的存储由 MemTable 和 SSTable 构成,MemTable 中数据的统计信息也非常重要,除了统一的收集之外,目前还会对 MemTable 中的表的行数进行收集,这个收集的代价相对较小,它的收集分散到各个优化过程中,每一次优化器的优化都会收集这部分的信息。

需要说明的是,由于数据库并不是一直在收集统计信息,所以会存在部分表、部分行没有统计信息的情况。对于这类情况,OceanBase 会使用一个缺省的统计信息。

数据库收集的最新的统计信息存储在内部表中,而频繁地访问内部表代价较大,而统计信息的更新并不是那么频繁,而且一张表、一个列的统计信息可以被多个查询使用。

基于上述原因引入了统计信息缓存(optimizer statistic cache)机制,本地使用一个 KV 缓存结构将统计信息缓存在内存当中,当优化器需要访问统计信息时,首先查询本地的缓存,当缓存中没有相应的统计信息时,再向内部表查询。

目前,sys 租户可以通过前述的内部表来查询表和列的统计信息,如下例所示,SQL 给出了一个使用内部表查询表、列的统计信息的示例。使用该 SQL 可以通过传入数据库名、表名和列名这三个信息的组合获取到包括表的行数、列的 NDV、列的 null 值数量以及列的最大最小值信息。