c 做网站好嘛,室内设计效果图欧式风格,营销网站大全,有那些专门做外贸的网站呀背景#xff1a;
统计信息在计算引擎的优化器模块中经常被提及#xff0c;尤其是在基于成本成本优化#xff08;CBO#xff09;框架中统计信息发挥着至关重要的作用。CBO旨在通过评估执行查询的可能方法#xff0c;并选择最有效的执行计划来提高查询性能。而统计信息则提…背景
统计信息在计算引擎的优化器模块中经常被提及尤其是在基于成本成本优化CBO框架中统计信息发挥着至关重要的作用。CBO旨在通过评估执行查询的可能方法并选择最有效的执行计划来提高查询性能。而统计信息则提供了关于数据分布、数据倾斜等方面的关键信息帮助CBO做出最优的决策。无论是传统数据库MySQL、PostgreSQL还是Hive、Spark计算引擎、Doris、StarRocks 等OLAP引擎都针对CBO模块做了大量开发工作。而统计信息作为影响CBO决策的最重要因素计算引擎需要对统计信息的搜集、加工、利用多个阶段进行打磨优化最终帮助用户业务提供成本最低的执行计划。
本文将会从统计信息的常见来源以及计算引擎如何利用统计信息多个方面着手综合多个计算引擎的CBO统计信息框架优化案例浅析计算引擎的CBO统计信息。 图1 计算引擎的优化器模块 一、统计信息的种类与来源
综合多个计算引擎的统计信息集成情况可以发现大家获取统计信息手段不尽相同一种是精准搜集统计信息一种是采用多种手段对数据进行评估获取统计信息。
常见的基本统计信息类型有min/max/ndv/totalSize/fileNum各家计算引擎会根据引擎特点继续扩展不同的统计信息如涉及到数据整体评估的统计信息MVC高频非NULL值、HiSTOGRAM直方图等。 1、基本类型统计信息
基本统计类型是相对精准的信息一般用户analyze语句获取的统计信息多数是这种min/max等基本信息。一般表级别、分区级别、字段级别都会有相应的统计信息。在不同的SQL业务中计算引擎会根据SQL中的谓词语句、table scan的具体表来分别利用哪种统计信息。
如select count(*) from testtbl; 显然这条语句会用到表级别统计信息select count(distinct id) from testtbl where date2024; 这条语句一般就会用到分区date以及字段id的统计信息。
基本类型统计信息一般都是实时获取定时任务获取。如大数据中Hive每次执行写入任务之后会有线程启动搜集写入数据的基本统计信息一定程度上保证统计信息实时准确StarRocks会有定时任务自动执行内表的统计信息搜集。 2、估算类型统计信息
估算类型统计信息一般泛指对数据集的一个整体评估能够在牺牲一定的准确性的情况下给出数据集的一个分布情况常见的如MVC。这种统计信息适合对于在大规模数据集下基本统计信息搜集相对代价较高且基本统计信息缺乏对整体数据集的极端分布如数据倾斜的体现而估算类型的统计信息能够告诉计算引擎数据的分布状况能够使任务避免数据倾斜等情况。
一般评估数据分布的统计信息都会采用histogram直方图多数计算引擎根据自身的业务特性实现了不同的直方图。直方图的基本原理是将数据排序后分成若干个bucket桶并记录每个桶中数据的最大值、最小值、频次出现等信息。常见的直方图有Equal-width Histogram、Equi-height Histogram等。像Doris和StarRocks均实现了Equi-height Histogram。Equi-width Histogram等宽直方图是将数据最大、小值之间的区间等分为N份每个桶中最大、小值之差都为整体数据最大、小值之差/N既所谓“等宽”。
Equi-height Histogram等高直方图它的桶宽度并不相等取而代之的是等高直方图会保证每个桶中数值的频次之和接近总行数的 1/N就是落入每个桶里的值数量尽量相等。数据数据分布范围比较大时也可以很好的保证误差。各种计算引擎会根据其擅长的业务特性去改进直方图以尽可能避免直方图落入局部最优的境地这里不过多详细解释直方图实现原理大家可以参考直方图的基本原理以及具体计算引擎实现去做细致研究。
一般情况下估算类型统计信息能够相对准确、相对高效的应用在一些大数据量的表上尤其是一些数据湖的大表PB级别但是一般的估算统计信息实现还是需要对数据做一遍整体扫描所以多数情况下的实现会判断大小表来决定是否整体数据评估信息搜集还是采样搜集。判断是否整体还是采样搜集各家计算引擎都会有不同的规则如StarRocks、Doris[Enchancement](statistics) Support sampling collection of statistics by weizhengte · Pull Request #18880 · apache/doris · GitHub搜集histogram直方图统计信息支持设置最大行数采样、根据比例进行采样也有的利用统计学方式如伯努利采样PrestoDBAdd reservoir_sample aggregation function by ZacBlanco · Pull Request #21296 · prestodb/presto · GitHub。
apache datasketches是另一种可用的非常高效的数据分布计算工具 目前基于apache datasketches算法库实现的直方图统计信息如Hive4.0草图中实现了各种近似估算方法很多方法都来源于数据库领域的论文算法。Sketch 结构即「数据草图」结构主要是为了计算海量的流式数据的概率指标而设计的一种数据结构。
一般占用固定大小的内存不随着数据量的增加而增大。这种结构通过巧妙地保存或丢弃一些数据的策略将数据流的信息抽象存储起来汇总成 Sketch 结构最终能根据 Sketch 结构还原始数据的分布实现基数统计、分位数计算等操作。
Spark3.5之后也使用apache datasketches实现了一些估算函数如ndvApache Spark ❤️ Apache DataSketches: New Sketch-Based Approximate Distinct Counting | Databricks Blog 基于sketch的估算函数能有效加速Spark对大数据集的一些数据分布估算比如在此之前统计数据集中的ndv一般spark用户都会count(distinct)这种计算十分耗时而且计算结果不会有临时存储每次都需要重新计算而datasketch能够利用经过验证的统计学算法快速的返回计算结果结果还可以持久化到sketch的存储中能够大大加速一些统计类型查询。 二、统计信息带来的常见收益
我们常常说统计信息能够加速查询能够优化执行计划那么从计算引擎角度来说统计信息利用最多的地方有哪些呢这里列举几个关键的点我们可以从不同的计算引擎中了解统计信息是怎样给用户的业务带来加速。 1、join选择
join能力是考量OLAP引擎的关键指标。如何在复杂的SQL语句中找到优化的join方式是CBO优化要做的事情。分析中常见的hash join涉及到大小表join一个关键的因素是怎么判断表的大小最直接的指标就是表的统计信息优化器根据表大小把小表作为build side来构造哈希表放入内存大表作为probe side这样可以有效避免数据的shuffle过程主流的计算引擎都会支持这种高效的join方式。
还有join reorder优化经常会根据计算过程中生成的临时统计信息对执行计划动态调整修改join算法简而言之join优化的基本要素就是需要有相对准确的统计信息最直接的统计信息如rowCount判断表大小。计算引擎一般利用这些基础的统计信息再结合一些reorder算法或者自定义的规则完成join查询的最优执行路径选择。 2、自适应任务执行
Adaptive Query Execution即AQE也是计算引擎高阶优化经常谈到的一个点。AQE执行可以理解为动态CBO可以根据运行期的一些临时数据的统计信息动态调整CBO选择的执行路径。典型的一个是Spark AQE其根据在运行时统计信息runtime statistics在查询执行的过程中进行动态DynamicSpark的查询优化AQE可以Spark运行query stage阶段准确获取统计信息然后进行CBO优化剩余的stage可以有效的动态合并Spark shuffle分区避免join阶段的一些数据倾斜问题。
无独有偶除了Spark AQE其他计算引擎也都有很多类似AQE优化。个人理解AQE优化一般针对中间数据有落盘的计算过程如上面提到的Sparkshuffle阶段所以可以推测其他有中间数据可以物化/落盘行为的计算引擎也可以去做这种优化。。
TrinoDB近年来增强了自身的容错计算能力即设计了中间shuffle数据落盘的一种计算模式fte可以在部分task运行失败时从磁盘中恢复中间执行数据然后重新执行TrinoDB的这种fte模式很适合使用AQE优化用于减少运行期启动不必要的task如Adaptive planning framework in FTE by gaurav8297 · Pull Request #20276 · trinodb/trino · GitHub 就是利用运行期统计信息做一些自适应优化
PrestoDB虽然没有fte执行模式但是其曾经也做过一些中间数据物化以提高task容错的开发如[Design] Exchange Materialization · Issue #12387 · prestodb/presto · GitHub 其思想会把中间数据物化成一个临时表供下游task消费那么很显然的优化就是获取这个中间表的统计信息来对下游的CBO执行计划做动态自适应调整Initial Support of Adaptive Optimization with Presto Unlimited by pguofb · Pull Request #14675 · prestodb/presto · GitHub。
类似的Hive3其实就有AQE优化核心思想缓存中间运行期的统计信息动态修正CBO执行计划、动态调整分区裁剪优化等[HIVE-17626] Query reoptimization using cached runtime statistics - ASF JIRA 。所以一旦清楚了AQE思想每一种计算引擎都可以根据自己运行期的统计信息特点做进一步动态优化给与业务最好的加速体验。 3、聚合下推优化
计算引擎中的聚合算子如sum、count是相对比较消耗计算资源的操作常规执行逻辑就是扫描数据的每一行来进行各种加减操作。但是如果已经搜集了存储表的统计信息如rowCount那么像这种count算子就是一个O(1)的简单元数据操作计算引擎不需要计算直接返回已经搜集的统计信息即可。
这种聚合下推的优化在各个计算引擎中基本都有实现尤其是针对底层存储采用Parquet/ORC这种开发式列存的文件格式如Iceberg的metadata文件就记录了详细的Parquet/ORC统计信息如Spark利用Iceberg的统计信息做一些下推的优化操作如TrinoDB也做了类似的基于统计信息的聚合下推操作优化Add aggregation pushdown support for count using Iceberg Metrics by osscm · Pull Request #15832 · trinodb/trino · GitHub 。
当然Hadoop之上经典的Hive计算引擎也早就有这种聚合下推优化比如有些Hive优化参数会控制是否启动MR分布式任务如参数hive.compute.query.using.stats该参数开启的情况下Hive计算引擎会去判断当前表的统计信息rowCount是否最新如果统计信息最新则在SQL语句中涉及到count的操作算子直接通过统计信息返回避免了启动分布式任务去计算。 三、小结
无论是数据库领域还是大数据领域CBO优化都是非常重要而统计信息则是作为CBO优化的最关键一环每一种计算引擎都会根据自身擅长的业务特点进行统计信息的搜集/利用从而获得最佳的执行计划。如何准确且轻量地获取统计信息并合理地应用在CBO框架以及其他优化中是一个非常值得探索的方向。 四、作者介绍
张步涛中国移动云能力中心数据库产品部-OLAP数据库开发工程师。主要参与OLAP内核研发/湖仓一体研发相关工作。