百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

让SQL优化器更准确!ADB PG版发布统计信息自动收集功能

mhr18 2025-02-15 16:33 33 浏览 0 评论

作者:王伟(盏一)


ADB PG 简介

AnalyticDB for PostgreSQL是阿里云上的MPP数据仓库服务,其内核采用PostgreSQL引擎,支持标准SQL 2003,兼容PostgreSQL/Greenplum,高度兼容 Oracle 语法生态;具有存储计算分离,在线弹性平滑扩容的特点;既支持任意维度在线分析探索,也支持高性能离线数据处理;是面向互联网、金融、证券、保险、银行、数字政务、新零售等行业有竞争力的数据仓库方案。



AnalyticDB for PostgreSQL采用MPP架构,实例由多个计算节点组成,存储容量随节点数线性扩展,且保持查询响应时间不变。

ADB PG 的 CBO 优化器基于表的统计信息,为查询选择最佳的查询计划。本次发布的 Auto Analyze 功能解决了在 ADB PG 实例使用过程中,由于未能及时执行 ANALYZE 收集统计信息导致了 CBO 优化器生成计划退化进而导致业务分析变慢的问题。


Analyze 重要性

当前 ADB PG 基于代价的优化器(以下简称 CBO),依赖于我们评估一个代价值用于衡量每种候选计划的代价,而代价的评估又依赖于收集的统计信息。在我们看来,CBO 和统计信息之间的关系犹如一把枪和弹药之间的关系,枪再好如果没有充足的弹药的话,那么无异于巧妇难为无米之炊。统计信息的收集就是为了给 CBO 提供足够多合理的信息,让 CBO 能够基于这些统计信息做出合理的决策。举个简单例子,假设我们有表 t 以及 idx_t_z 如下所示:

create?table?t(i?int?,?j?int,?z?int);?
create?index?idx_t_z?on?t(z);?
insert?into?t?select?i,?i,?i?from?generate_series(1,?2)?i;??--?1?
insert?into?t?select?i,?i,?i?from?generate_series(1,?3333333)?i;??--?2?
insert?into?t?select?i,?i,?20181218?from?generate_series(1,?10)?i;

注:*左右滑动阅览


这里第1处 insert 会触发 ADB PG AutoStats 机制,此时会对表 t 进行一次 ANALYZE,并收集相关统计信息。接着我们使用 EXPLAN ANALYZE 来执行一条简单查询并输出查询的执行计划:

tmp=# explain analyze select * from t where z = 20181218; 
Gather?Motion?3:1??(slice1;?segments:?3)??(cost=0.00..2.02?rows=1?width=12)?(actual?time=287.952..743.833?rows=10?loops=1)?
?->??Seq?Scan?on?t??(cost=0.00..2.02?rows=1?width=12)?(actual?ti?me=287.428..287.430?rows=5?loops=1)?
?????????Filter:?(z?=?20181218)?
Planning?time:?1.242?ms?
?  (slice0)????Executor?memory:?59K?bytes.?
???(slice1)????Executor?memory:?42K?bytes?avg?x?3?workers,?42K?byt?es?max?(seg0).?
Memory?used:??128000kB?
Optimizer:?Postgres?query?optimizer?
Execution?time:?744.675?ms

注:*左右滑动阅览


可以看到,由于在表 t 创建之后,仅在第一次 insert 时触发了 ANALYZE,在数据更新后未能及时更新统计信息,使得优化器在优化时看到的统计信息中记录着表 t 总行数为 2,使得 CBO 优化器这时错认为 SeqScan 比 IndexScan 效率更高。但如果我们这里手动执行下 ANALYZE:

tmp=# ANALYZE t; 
ANALYZE?
tmp=#?explain?analyze?select?*?from?t?where?z?=?20181218;?
Gather?Motion?3:1??(slice1;?segments:?3)??(cost=0.18..8.20?rows=1?width=12)?(actual?time=0.429..0.439?rows=10?loops=1)?
?->??Index?Scan?using?idx_t_z?on?t??(cost=0.18..8.20?rows=1?widt?h=12)?(actual?time=0.014..0.016?rows=5?loops=1)?
????????Index?Cond:?(z?=?20181218)?
Planning?time:?1.305?ms?
?? (slice0)????Executor?memory:?92K?bytes.?
???(slice1)????Executor?memory:?60K?bytes?avg?x?3?workers,?60K?byt?es?max?(seg0).?
Memory?used:??128000kB?
Optimizer:?Postgres?query?optimizer?
Execution?time:?1.322?ms

注:*左右滑动阅览


可以看到由于 CBO 使用了更精确的统计信息,所以其也生成更优的执行计划,使得查询执行时间从 700ms 降低到 1ms。

更精准的统计信息除了能帮助优化器生成更高效的执行计划之外;也能够使得 ADB PG 近期发布的多维排序得到更好的排序效果,排序效果越好,对查询就有越明显的加速。


AutoStats 介绍

如上所示,正因为 ANALYZE 重要性,为了提升用户体验,ADB PG 引入了 AutoStats 机制。AutoStats 机制有如下三种工作模式,受配置 gp_autostats_mode 控制。

  1. ON_NO_STATS。此时意味着在用户执行了 Insert/Update/Delete 等 DML 操作之后,ADB PG 会查询 DML 目标表在 DML 之前的状态,若目标表在 DML 之前是空表,那么在 DML 之后,此时 ADB PG 会在同一事务内对目标表触发一次 ANALYZE 操作。这也是当前 ADBPG 线上默认配置。
  2. ON_CHANGE。此时意味着在用户执行了 DML 操作之后,ADB PG 会判断本次 DML 操作影响到的行数,若影响行数超过一定阈值,便会对目标表触发一次 ANALYZE 操作。
  3. NONE。此时意味着关闭 AutoStats 系统。

可以看到 AutoStats 判断是否对目标表触发 ANALYZE 操作只依据了最近一次 DML 操作的结果,所以 AutoStats 更适合 ETL 业务。但随着 ADB PG HTAP 能力的提升,以及与周边生态系统链路的打通,越来越多的用户倾向于以流式的方式将数据导入到 ADB PG 中,比如使用阿里云数据传输服务。这导致了 AutoStats 越来越乏力。从上面举的例子也可以看到,AutoStats 只会在第一次 Insert 之后触发一次 ANALYZE 操作,使得在第二、三次 insert 之后,表 t 的统计信息与实际情况完全不符,这也直接导致了 CBO 未能生成更优的执行计划。


引入 Auto Analyze

为此 ADB PG 开发了适合场景更广、对流式插入更友好的 Auto Analyze 系统。Auto Analyze 会为每张表记录自上次 Analyze 以来所有 Insert/Update/Delete 影响到行数的累加值,之后基于这个累加值,结合表本身大小,来决策是否需要为表执行 Analyze 操作。另外 Auto Analyze 会异步地执行 Analyze 操作,与 AutoStats 在用户业务事务内同步地执行 Analyze 操作相比,异步 Analyze 执行对用户业务基本上无感,也不会再有同步执行 Analyze 操作而可能导致的死锁等其他问题。而且秉承着拥抱、回馈、融合、回报的开源思想,ADB PG Auto Analyze 也已经贡献并合入了 Greenplum master 分支。

在开启 Auto Analyze 的前提下,我们再一次模拟执行文章开头中举的例子,如下所示在执行完第3条 insert 之后,Auto Analyze 系统也触发了对表 t 的一次 ANALYZE 操作。

tmp=# select objid::regclass, staactionname, stasubtype from pg_stat_last_operation where objid = 't'::regclass order by statime desc;
 objid | staactionname | stasubtype
-------+---------------+------------
 t     | ANALYZE       | AUTO
 t     | CREATE        | TABLE
(2?rows)

注:*左右滑动阅览


此时用户不再需要手动执行 ANALYZE,也能使 CBO 生成更优的执行计划:

Gather Motion 3:1  (slice1; segments: 3)  (cost=0.18..8.20 rows=1 width=12) (actual time=0.765..0.773 rows=10 loops=1)
  ->  Index Scan using idx_t_z on t  (cost=0.18..8.20 rows=1 width=12) (actual time=0.013..0.015 rows=5 loops=1)
        Index Cond: (z = 20181218)
Planning time: 1.034 ms
  (slice0)    Executor memory: 92K bytes.
  (slice1)    Executor memory: 60K bytes avg x 3 workers, 60K bytes max (seg0).
Memory used:  128000kB
Optimizer: Postgres query optimizer
Execution?time:?1.647?ms

注:*左右滑动阅览


Auto Analyze 实现


5.1 PG Auto Analyze 实现


在介绍 ADB PG Auto Analyze 实现之前,我们首先看下 PostgreSQL 中是如何实现 Auto Analyze 的。PostgreSQL Auto Analyze 的实现依赖着两个组件:Statistics Collector,Autovacuum。其中 Autovacuum 组件,简单来说,就是周期性遍历每个库,对于库中每个表,根据 Statistics Collector 中这张表相关的统计信息来判断是否需要为这张表触发 Analyze, Vacuum 等操作。Statistics Collector 组件负责收集、保存、持久化 PG 运行中产生的各种 metric 信息,如表的增、删、改行数等。Statistics Collector 收集到的所有信息都保存在内存中。在 Statistics Collector 进程关闭时,会将内存中的统计信息持久化到磁盘文件中。在 Statistics Collector 进程启动时,也会从磁盘文件中读取之前持久化的统计信息到内存中。Statistics Collector 自身同时也是一个 udp server,监听着一个特定端口。在 PG 运行中,backend 会在适当时候将自身收集到的 metric 打包成 udp message 发送给 Statistics Collector。下面以 PgStat_StatTabEntry 中信息的收集为例演示一下此过程:



其中 pgStatTabList 指针指向的结构等同于 LinkedList,每个 backend 都会将自身收集到表级别的 metric 存放在该数组相应 PgStat_TableStatus 中。

PgStat_TableStatus::trans 指针指向的结构等同于 Vec ,其内通过 PgStat_TableXactStatus 存放着当前表在每个事务级别内的统计信息。PgStat_SubXactStatus 结构存放着一个特定事务级别内所有 PgStat_TableXactStatus 结构,存放着该事务级别内发生的所有统计信息。pgStatXactStack 总是指向着当前事务级别对应的 PgStat_SubXactStatus 结构。当在某个事务级别内 backend 打开表准备执行增删改时,会从 pgStatTabList 指向的数组中选择一个 PgStat_TableStatus 元素赋值给 RelationData::pgstat_info。之后在执行 IUD(Insert/Update/Delete) 操作时,backend 会更新当前事务级别上特定表对应的 PgStat_TableXactStatus 结构。每当一个子事务 commit/rollback 时都会将本级别事务内所有 PgStat_TableXactStatus 统计信息合并到父事务中。在顶层事务 commit/rollback 时会将 PgStat_TableXactStatus 的统计信息合并到
PgStat_TableStatus.t_counts 中。最后每当 backend 进入 idle 状态(或者退出)时,会将 pgStatTabList 中所有有效的 PgStat_TableStatus 打包成 udp message 发送给 Statistics Collector,之后将 pgStatTabList 中统计信息清零。


5.2 ADB PG Auto Analyze 实现


所以 ADB PG Auto Analyze 的实现主要便是在 Insert/Update/Delete 执行结束之后,收集各个计算节点返回的 Insert/Update/Delete 在各自节点内影响到的行数,之后累加得到 Insert/Update/Delete 影响到的总行数,之后将这个信息按照 PG Statistics Collector 中做法记录在对应的 PgStat_TableXactStatus 结构中。最后会在适当时候发送给 ADB PG master 节点的 Statistics Collector 进程。


未来展望

Auto Analyze 的引入使得用户在使用 ADB PG 实例的过程中,统计信息总是能被及时地收集。这也使得用户的业务分析将总是能得到较优的执行计划,业务分析 SQL 的执行性能将不再会由于统计信息过时而急剧下降。另外在 Auto Analyze 搭建的基础设施上,结合着线上用户在使用 ADB PG 中遇到的一些问题,我们也有了接下来的目标:实现 Auto Vacuum 功能。与 Analyze 操作一样,Vacuum 在 ADB PG 也扮演着重要的角色,相信 Auto Vacuum 的引入也会进一步加强 ADB PG 的用户体验。


#阿里云# #数据库#


点击“了解更多”查看详情

相关推荐

甲骨文签署多项大型云协议,其一未来可贡献超300亿美元年收入

IT之家7月1日消息,根据甲骨文Oracle当地时间6月30日向美国证券交易委员会(SEC)递交的FORM8-K文件,该企业在始于2025年6月1日的202...

甲骨文获TEMU巨额合同,后者大部分基础设施将迁移至Oracle云

IT之家6月23日消息,Oracle甲骨文创始人、董事长兼首席技术官LarryEllison(拉里埃里森)在本月早些时候的2025财年第四财季和全财年财报电话会议上表示,Oracle...

Spring Boot 自定义数据源设置,这些坑你踩过吗?

你在使用SpringBoot进行后端开发的过程中,是不是也遇到过这样的问题:项目上线后,数据库连接总是不稳定,偶尔还会出现数据读取缓慢的情况,严重影响了用户体验。经过排查,发现很大一部分原因竟然...

一个开箱即用的代码生成器(一个开箱即用的代码生成器是什么)

今天给大家推荐一个好用的代码生成器,名为renren-generator,该项目附带前端页面,可以很方便的选择我们所需要生成代码的表。首先我们通过git工具克隆下来代码(地址见文末),导入idea。...

低代码建模平台-数据挖掘平台(低代码平台的实现方式)

现在来看一下数据连接。·这里是管理数据连接的空间,点击这里可以新增一个数据连接。·输入连接名称,然后输入url,是通过gdbc的方式去连接的数据库,目前是支持mysql、oracle以及国产数据库达梦...

navicat 17.2.7连接oracle数据库提示加载oracle库失败

系统:macOS15.5navicat版本:navicatpremiumlite17.2.7连接oracle测试报错:加载oracle库失败【解决办法】:放达里面找到程序,显示简介里面勾选“使...

开源“Windows”ReactOS更新:支持全屏应用

IT之家6月17日消息,ReactOS团队昨日(6月16日)在X平台发布系列推文,公布了该系统的最新进展,包括升级Explorer组件,支持全屏应用,从Wine项目引入了...

SSL 推出采用全模拟内置混音技术的模拟调音台Oracle

英国调音台传奇品牌SolidStateLogic宣布推出Oracle——一款采用全模拟内置混音技术的调音台,在紧凑的AWS尺寸机箱内集成了大型调音台的功能。该调音台提供24输入和...

47道网络工程师常见面试题,看看有没有你不会的!

你们好,我的网工朋友。网络工程师面试的时候,都会被问到什么?这个问题其实很泛,一般来说,你肯定要先看明白岗位需求写的是什么。基本上都是围绕公司需要的业务去问的。但不可否认的是,那些最基础的概念,多少也...

汉得信息:发布EBS系统安装启用JWS的高效解决方案

e公司讯,从汉得信息获悉,近日,微软官方宣布InternetExplorer桌面应用程序将于2022年6月15日正式停用。目前大部分客户都是使用IE浏览器打开EBS的Form界面,IE停用后,只能使...

36.9K star ! 推荐一个酷炫低代码开发平台!功能太强!

前言最近在逛github,看看能不能搜罗到一些对自己有帮助的开源软件。不经意间看到一个高star的java开源项目:jeecg-boot。进入在线演示版一看,感叹实在是太牛了!此开源项目不管是给来学习...

Linux新手入门系列:Linux下jdk安装配置

本系列文章是把作者刚接触和学习Linux时候的实操记录分享出来,内容主要包括Linux入门的一些理论概念知识、Web程序、mysql数据库的简单安装部署,希望能够帮到一些初学者,少走一些弯路。注意:L...

手把手教你在嵌入式设备中使用SQLite3

摘要:数据库是用来存储和管理数据的专用软件,使得管理数据更加安全,方便和高效。数据库对数据的管理的基本单位是表(table),在嵌入式linux中有时候它也需要用到数据库,听起来好难,其实就是几个函数...

JAVA语言基础(java语言基础知识)

一、计算机的基本概念什么是计算机?计算机(Computer)全称:电子计算机,俗称电脑。是一种能够按照程序运行、自动高速处理海量数据的现代化智能电子设备。由硬件和软件组成、没有安装过任何软件的计算机称...

再见 Navicat!一款开源的 Web 数据库管理工具!

大家好,我是Java陈序员。在日常的开发工作中,常常需要与各种数据库打交道。而为了提高工作效率,常常会使用一些可视化工具进行操作数据库。今天,给大家介绍一款开源的数据库管理工具,无需下载安装软件,基...

取消回复欢迎 发表评论: