从一到无穷大 #43:Presto History Based Optimizer,基于PlanNode粒度统计的查询计划选择策略

在这里插入图片描述本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。

文章目录

  • 引言
  • Motivation
  • Architecture
  • HBO Scenario
  • Experiments
  • 结束语

引言

过年回家这件事在挚友的劝导下,在不回去和一直呆在家之间选择了提前回深圳,从绝大多数方面看这绝对可以算是最近一段时间内做的最正确的决策之一,最直观的结果就是拥有了完整三天个人假期,可以彻彻底底的放松下,提前进入下2025H1的项目攻坚状态,把自己的心态拉回来。

过年期间并不算全部都是颓废的生活,除去阖家团圆的传统剧情,更具现实意义的是在挚友的推荐和自我兴趣驱使下读完了《亲密关系》《恶意》《黄仁勋:英伟达之芯》《廊桥遗梦》,还有一本尚在 todo list 内的《信》,其实对于阅读这件事情我一直很功利,这也是为什么之前只有在交通工具上时我才会读非技术书,平时的大把时间也都是在读领域相关的paper,但是慢慢的发觉,仅有领域知识是远远不够解答所有的困惑的。

回到假期,深圳的三天除了正常的锻炼,看朋友发给我的自媒体资料这两个必做项之外,我一直想,在有限的剩余时间是输入,输出还是躺着?

输出有三个选择:

  1. 我非常想写《黄仁勋:英伟达之芯》这本书的书评,虽然传记类文章存在部分魔幻色彩,但是Jensen的经历毋庸置疑是传奇的,而且NVIDIA的崛起之路不夸张的讲能让一个痴迷技术的理工人看到颅内高潮,相比之下《腾讯传》就显得无趣多了。
  2. 我最近在做时序数据库的MPP(Massively Parallel Processing),免不了需要去适配Exchange算子,也确实没研究过其他的实现,但Velox中的实现的异步方式确实让人耳目一新,其实现基于ExchangeQueueExchangeClientExchangeSources三个类,新的实现只需要继承ExchangeSources就好,这里是绝对值得输出的,且目前网上这里的资料是零。
  3. Presto的HBO,也就是本文,这篇paper年前就看完了,我其实看绝大多数paper不会写文章,但这篇文章揭示了一个现象,其与我的工作有一些想法上的联系,即越细的监控粒度能够带来更多的可能性,如果能持续下压性能和成本,这就是绝对符合公司(部门)战略的事情,而且我最近也在负责优化器部分的重构,HBO的思路有可能在做部分修改后应用到X-Stor来。长久以来看惯了很多软文的宏大叙事,但其实绝大多数人做的事情就是没有颠覆性价值,抠出一点意义已经是值得投入以年计的时间了,这虽然让人有时觉得沮丧,无力且压抑,但是耐心沉淀对于个人来讲也是必要的,毕竟Jensen也曾在AMD打工。

输入有两个选择:

  1. 把新年档的哪吒,唐探,封神看下,事实上已经快忘了我上次在影院看电影是多少年前了
  2. 还有两本书想看

躺着:

  1. 思考当下生活的核心矛盾点,思考未来想做好的事情,思考我真正想要的东西是什么

正如现在看到的这样,最终的决策是选择输出HBO,如果文章写完还有点剩下的时间,那就去深圳湾人才公园水池旁边的草坪上躺着看星星。

Motivation

Presto的Cardinality Estimator依赖于如下统计信息,粒度为partition级别:

  1. Overall cardinality of the partition
  2. Column statitstics including
    1. Average size
    2. Number of distinct values
    3. Number of null values
    4. Range(min/max) for the values

传统的CBO(Cost Based Optimizer)通常依靠离线过程收集有关输入数据的统计信息,文章开篇点出CBO存在复杂查询下Cardinality Estimation不准确的情况,进而导致查询计划的选择无法达到最优,具体的,存在如下问题:

  1. 需要在查询前执行分析
  2. 做出了很多Simplifying Assumptions,比如data uniformityindependence of filters and columns,在复杂表达式下通常无法准确预估Selectivity
  3. 使用更复杂的统计信息,比如multi-columnjoin histograms,但是需要额外的空间和时间,且很难处理,绝大多数系统没有实现

LBO(Learning Based Optimizer)也是最近几年比较火爆的一个方向,其最大的优势是克服了传统CBO的很多Simplifying Assumptions,但是也有如下缺点:

  1. 训练和改进模型需要大量的投入
  2. 可解释性差

HBO(History Based Optimizer) 在 Operator Node 级别统计 Query Execution Statistics,并使用这些数据来预测相似查询的未来性能。HBO基于一种假设,即用户查询虽然复杂,但本质上是重复性的,一般使用使用模版生成相同结构的查询,这会造成查询计划基本一致,进而可以通过简易的方法找到之前的统计信息,然后用来执行精确的估计,这种假设从我们的经验来看是对的。

HBO解决了之前无法解决的问题:

  1. Accuracy:在实际执行运行期间记录统计数据,并在运算符级别进行跟踪,消除了使用基础表统计数据引入的较大估计误差。
  2. Automation:每次查询运行时,历史记录都由轻量级进程跟踪,从而避免了采样开销或模型训练。
  3. Adaptiveness:对基础数据分布的更改会自动反映在跟踪的历史记录中,并用于未来的优化。
  4. Explicability:用户和 DBA 可以查看估计数据的来源以及它与实际值的差距。

Architecture

Presto CBO可以为简单查询生成准确的估计,但随着查询变得越来越复杂,误差幅度会呈指数级增长。

HBO希望做到的约束如下:

  1. Estimates need to be accurate:解决复杂查询下的基数估计不准的问题
  2. Accommodate changes to both data and queries:数据和查询不是静态的,但是一般也不会短时间存在巨大波动,HBO要能适应数据变化
  3. Minimal overhead to query processing:轻量级统计,无需大量计算
  4. Ease of use and operation:可调试性,且用户易于使用
  5. Seamless integration with classic methods for deriving cost:HBO不可用回退至CBO

请添加图片描述

HBO的思路非常简单,有几个不那么难的难点需要解决:

  1. 查询模版虽然不变,但是其中参数和查询条件数量存在变化
  2. 统一查询模版的查询计划可能存在差异,因为可能被不同的优化策略该写过
  3. 搜索类似查询计划的开销很大,毕竟每个查询都会有数据存储,且在执行之前都会做统计信息获取

这些难点可以用三个工程方法解决:

  1. 模版归一化,具体的操作是Canonicalizing Table scansCanonicalizing plan nodesPruning constants
  2. 将stat-equav的计划存储在一起
  3. 哈希

简单来说整个HBO可以分为以下几个步骤:

  1. 对plan nodes归一化,并且找到stat-equav的plan nodes
  2. worker执行完plan后,把统计信息交给Coordinator
  3. Coordinator负责将plan及其stats-equav plan nodes统计信息写入到redis 里面
  4. 未来查询的时候,同样可以根据归一化的plan node去redis里面拿统计信息

肉眼可见的简单,但是也伴随着极大的工程化落地工作量

HBO Scenario

目前有如下场景用到了HBO:

  1. Join reordering:HBO可以准确的拿到之前join算子的准确数据,自然可以选择最优的连接顺序
  2. Join distribution type:拿到join算子的准确数据,即不同表的真实数据输入,自然可以选择最优的join方法
  3. Partial aggregations:通过aggregation算子的输入大小就知道是否需要做二级aggregations了
  4. Skew mitigation:可以知道算子级别准确的null数量,而不是基于假设的估算,这样就可以判断是否应用优化规则
  5. Scaled writers:write多文件小,write小写入性能不足,通过历史记录选择相对较优的write数量

Experiments

请添加图片描述
简单查询CBO已经足够,复杂查询HBO可以带来更优的查询策略

请添加图片描述
因为选择了更优的执行计划,性能提升很明显

请添加图片描述
在presto的场景下,10%的查询有2.5x的性能提升,中位数为1-1.2x的性能提升,但是也有10%有8%的性能下降

请添加图片描述
HBO的开销论文中提到占整个查询的0.5%左右,大概几毫秒,大多数是网络开销。

结束语

在我们的场景中查询简单,且查询场景多为交互式,对时延要求高,虽然加个几毫秒问题也不是特别大,但是目前除了Partial aggregations没有看到其他很好的使用场景,也许可以先研究下presto中150多种优化策略具体有哪些使我们能用的比较重要。

参考:

  1. How Good Are Query Optimizers, Really? vldb2015
  2. Presto’s History-based Query Optimizer 论文笔记
  3. How Good Are Query Optimizers, Really?论文笔记
  4. 数据库分布式Join类型及意义Broadcast Join、Shuffle Join 和 Colocate Join

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/894532.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++】继承(下)

大家好,我是苏貝,本篇博客带大家了解C的继承(下),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 5.继承与友元6.继承与静态成员7.复杂的菱形继承及菱形虚拟继承8.继…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)

文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…

【流媒体】搭建流媒体服务器

搭建Windows Nginx服务器 搭建 下载nginx工具包解压至本地,并在cmd窗口中切换至nginx所在的本地目录修改 conf/nginx.conf 文件,更改其端口号 server中的 listen的端口号从 80改为 8080,因为80经常被其他服务占用,导致无法打开 …

【Linux】24.进程信号(1)

文章目录 1. 信号入门1.1 进程与信号的相关知识1.2 技术应用角度的信号1.3 注意1.4 信号概念1.5 信号处理常见方式概览 2. 产生信号2.1 通过终端按键产生信号2.2 调用系统函数向进程发信号2.3 由软件条件产生信号2.4 硬件异常产生信号2.5 信号保存 3. 阻塞信号3.1 信号其他相关…

编程题-电话号码的字母组合(中等)

题目: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 解法一(哈希表动态添加)&#x…

数据结构课程设计(三)构建决策树

3 决策树 3.1 需求规格说明 【问题描述】 ID3算法是一种贪心算法,用来构造决策树。ID3算法起源于概念学习系统(CLS),以信息熵的下降速度为选取测试属性的标准,即在每个节点选取还尚未被用来划分的具有最高信息增益的…

Node.js下载安装及环境配置

目录 一、下载 1. 查看电脑版本,下载对应的安装包 2. 下载路径下载 | Node.js 中文网 二、安装步骤 1. 双击安装包 2. 点击Next下一步 3. 选择安装路径 4. 这里我选择默认配置,继续Next下一步(大家按需选择) 5. 最后inst…

使用python实现与本地ollama部署的deepseek对话

专栏总目录 按照ollama官方doc的example操作,没有成功与本地ollama上的deepseek-r1:1.5b通讯后,发现vscode可以调用本地ollama上的deepseek模型。 为了实现与ollama上的deepseek模型通讯,我使用wireshark对本地回环地址进行侦听后&#xff0c…

【大模型理论篇】最近大火的DeepSeek-R1初探系列1

1. 背景介绍 这一整个春节,被DeepSeek-R1刷屏。各种铺天盖地的新闻以及老板发的相关信息,着实感受到DeepSeek-R1在国外出圈的震撼。 DeepSeek推出了新的推理模型:DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是一个在没有经过监督微调…

Pandoc, Zotero, JabRef 管理论文引用,生成参考文献 | 撰写论文 paper

书接上回,使用 Obsidian, Zotero, JabRef, Pandoc, Markup-Markdown | 撰写论文 paper 管理论文引用,生成参考文献 TL; DR导出 bibliography 文件JabRefZotero 参考文献引用语法reference-docLinks TL; DR 安装 pandoc v3.6.2. 使用一下命令&#xff0c…

计算机网络——流量控制

流量控制的基本方法是确保发送方不会以超过接收方处理能力的速度发送数据包。 通常的做法是接收方会向发送方提供某种反馈,如: (1)停止&等待 在任何时候只有一个数据包在传输,发送方发送一个数据包,…

【C语言入门】解锁核心关键字的终极奥秘与实战应用(三)

目录 一、auto 1.1. 作用 1.2. 特性 1.3. 代码示例 二、register 2.1. 作用 2.2. 特性 2.3. 代码示例 三、static 3.1. 修饰局部变量 3.2. 修饰全局变量 3.3. 修饰函数 四、extern 4.1. 作用 4.2. 特性 4.3. 代码示例 五、volatile 5.1. 作用 5.2. 代码示例…

2.2 实现双向链表的快速排序

实现一个双向链表的快速排序。 1>程序代码 #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h>…

力扣动态规划-19【算法学习day.113】

前言 ###我做这类文章一个重要的目的还是记录自己的学习过程&#xff0c;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&#xff01;&#xff01;&#xff01; 习题 1.矩形中移动的最大次数 题目链接…

Gurobi基础语法之 addConstr, addConstrs, addQConstr, addMQConstr

在新版本的 Gurobi 中&#xff0c;向 addConstr 这个方法中传入一个 TempConstr 对象&#xff0c;在模型中就会根据这个对象生成一个约束。更重要的是&#xff1a;TempConstr 对象可以传给所有addConstr系列方法&#xff0c;所以下面先介绍 TempConstr 对象 TempConstr TempC…

neo4j-community-5.26.0 create new database

1.edit neo4j.conf 把 # The name of the default database initial.dbms.default_databasehonglouneo4j # 写上自己的数据库名称 和 # Name of the service #5.0 server.windows_service_nameneo4j #4.0 dbms.default_databaseneo4j #dbms.default_databaseneo4jwind serve…

unity实现回旋镖函数

最近学习unity2D&#xff0c;想实现一个回旋镖武器&#xff0c;发出后就可以在角色周围回旋。 一、目标 1.不是一次性的&#xff0c;扔出去、返回、没有了&#xff1b;而是扔出去&#xff0c;返回到角色后方相同距离&#xff0c;再次返回&#xff1b;再次返回&#xff0c;永远…

【C++基础】字符串/字符读取函数解析

最近在学C以及STL&#xff0c;打个基础 参考&#xff1a; c中的char[] ,char* ,string三种字符串变量转化的兼容原则 c读取字符串和字符的6种函数 字符串结构 首先明确三种字符串结构的兼容关系&#xff1a;string>char*>char [] string最灵活&#xff0c;内置增删查改…

SpringBoot源码解析(九):Bean定义接口体系

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…

C++模板编程——可变参函数模板

目录 1. 可变参函数模板基本介绍 2. 参数包展开——通过递归函数 3. 参数包展开——通过编译期间if语句(constexpr if) 4. 重载 5. 后记 进来看的小伙伴们应该对C中的模板有了一定了解&#xff0c;下面给大家介绍一下可变参函数模板。过于基础的概念将不仔细介绍。 1. 可变…