CBO 统计信息
本文介绍 StarRocks CBO 优化器(Cost-based Optimizer)的基本概念,以及如何为 CBO 优化器采集统计信息来优化查询计划。StarRocks 2.4 版本引入直方图作为统计信息,提供更准确的数据分布统计。
3.2 之前版本支持对 StarRocks 内表采集统计信息。从 3.2 版本起,支持采集 Hive,Iceberg,Hudi 表的统计信息,无需依赖其他系统。
什么是 CBO 优化器
CBO 优化器是查询优化的关键。一条 SQL 查询到达 StarRocks 后,会解析为一条逻辑执行计划,CBO 优化器对逻辑计划进行改写和转换,生成多个物理执行计划。通过估算计划中每个算子的执行代价(CPU、内存、网络、I/O 等资源消耗),选择代价最低的一条查询路径作为最终的物理查询计划。
StarRocks CBO 优化器采用 Cascades 框架,基于多种统计信息进行代价估算,能够在数万级别的执行计划中,选择代价最低的执行计划,提升复杂查询的效率和性能。StarRocks 1.16.0 版本推出自研的 CBO 优化器。1.19 版本及以上,该特性默认开启。
统计信息是 CBO 优化器的重要组成部分,统计信息的准确与否决定了代价估算是否准确,对于 CBO 选择最优 Plan 至关重要,进而决定了 CBO 优化器的性能好坏。下文详细介绍统计信息的类型、采集策略、以及如何创建采集任务和查看统计信息。
统计信息数据类型
StarRocks 会采集多种统计信息,为查询优化提供代价估算的参考。
基础统计信息
StarRocks 默认定期采集表和列的如下基础信息:
-
row_count: 表的总行数
-
data_size: 列的数据大小
-
ndv: 列基数,即 distinct value 的个数
-
null_count: 列中 NULL 值的个数
-
min: 列的最小值
-
max: 列的最大值
全量的统计信息存储在 StarRocks 集群 _statistics_ 数据库下的 column_statistics 表中,您可以在 _statistics_ 数据库下查看。查询时会返回类似如下信息:
SELECT * FROM _statistics_.column_statistics\G
*************************** 1. row ***************************
table_id: 10174
partition_id: 10170
column_name: is_minor
db_id: 10169
table_name: zj_test.source_wiki_edit
partition_name: p06
row_count: 2
data_size: 2
ndv: NULL
null_count: 0
max: 1
min: 0
直方图
从 2.4 版本开始,StarRocks 引入直方图 (Histogram)。直方图常用于估算数据分布,当数据存在倾斜时,直方图可以弥补基础统计信息估算存在的偏差,输出更准确的数据分布信息。
StarRocks 采用等深直方图 (Equi-height Histogram),即选定若干个 bucket,每个 bucket 中的数据量几乎相等。对于出现频次较高、对选择率(selectivity)影响较大的数值,StarRocks 会分配单独的桶进行存储。桶数量越多时,直方图的估算精度就越高,但是也会增加统计信息的内存使用。您可以根据业务情况调整直方图的桶个数和单个采集任务的 MCV(most common value)个数。
直方图适用于有明显数据倾斜,并且有频繁查询请求的列。如果您的表数据分布比较均匀,可以不使用直方图。直方图支持的列类型为数值类型、DATE、DATETIME 或字符串类型。
目前直方图仅支持手动抽样采集。直方图统计信息存储在 StarRocks 集群 _statistics_ 数据库的 histogram_statistics 表中。查询时会返回类似如下信息:
SELECT * FROM _statistics_.histogram_statistics\G
*************************** 1. row ***************************
table_id: 10174
column_name: added
db_id: 10169
table_name: zj_test.source_wiki_edit
buckets: NULL
mcv: [["23","1"],["5","1"]]
update_time: 2023-12-01 15:17:10.274000
采集类型
随着表的导入或者删除操作,表的大小和数据分布会频繁更新,因此需要定期更新统计信息,以确保统计信息能准确反映表中的实际数据。在创建采集任务之前,您需要根据业务场景决定使用哪种采集类型和采集方式。
StarRocks 支持全量采集 (full collection) 和抽样采集 (sampled collection)。全量采集和抽样采集均支持自动和手动采集方式。
| 采集类型 | 采集方式 | 采集方法 | 优缺点 |
|---|---|---|---|
| 全量采集 | 自动或手动 | 扫描全表,采集真实的统计信息值。按照分区(Partition)级别采集,基础统计信息的相应列会按照每个分区采集一条统计信息。如果对应分区无数据更新,则下次自动采集时,不再采集 该分区的统计信息,减少资源占用。全量统计信息存储在 _statistics_.column_statistics 表中。 | 优点:统计信息准确,有利于优化器更准确地估算执行计划。缺点:消耗大量系统资源,速度较慢。从 2.4.5 版本开始支持用户配置自动采集的时间段,减少资源消耗。 |
| 抽样采集 | 自动或手动 | 从表的每个分区中均匀抽取 N 行数据,计算统计信息。抽样统计信息按照表级别采集,基础统计信息的每一列会存储一条统计信息。列的基数信息 (ndv) 是按照抽样样本估算的全局基数,和真实的基数信息会存在一定偏差。抽样统计信息存储在 _statistics_.table_statistic_v1 表中。 | 优点:消耗较少的系统资源,速度快。 缺点:统计信息存在一定误差,可能会影响优化器评估执行计划的准确性。 |
采集统计信息
StarRocks 提供灵活的信息采集方式,您可以根据业务场景选择自动采集、手动采集,也可以自定义自动采集任务。
默认情况下,StarRocks 会周期性自动采集表的全量统计信息。默认检查更新时间为 5 分钟一次,如果发现数据的更新比例满足条件,会自动触发采集。全量采集可能会消耗大量的系统资源,如果您不希望使用自动全量采集,可以设置 FE 配置项 enable_collect_full_statistic 为 false,系统会停止自动全量采集,根据您创建的自定义任务进行定制化采集。