原文:《Preventing bad plans by bounding the impact of cardinality estimation errors》

摘要

  • 文章定义了一个衡量基数估计好坏的criterion:Q-error.

    • 对于我们给定的一个bound(边界),如果q-error小于bound,查询优化器将产生一个最佳计划。
    • 如果q-error以q为一个bound,那么我们就可以认为产生的执行计划最多比最佳计划差\(q^4\)倍。
  • 基于上述发现,文章展示了如何在q-error下找到最佳的近似值。
  • 这些技术可以用来构建基数估计synopsis(概要)

简介

  • 成本计算包括两方面:

    • 基数估计:对查询中间结果大小的估计,是成本计算的重点,往往会造成比较大的估计偏差而造成成本计算的错误。
    • 代数运算符的成本估计:多查询中进行的代数运算进行成本估计,往往估计的比较准确,与真实结果不到\(3\%\)的错误率。
  • 针对成本计算的现状提出了几个问题

    • Q1:基数估计总是出错,我们怎么衡量基数估计出现的错误大小?这个问题是最基本的问题
    • Q2A:如何最大限度的减少错误的传播
    • Q2B:是否存在一个对错误的边界,当错误在这个边界内,得到的执行计划仍然是最优计划,如果这个边界存在,它们具体是什么样的?
    • Q2C:如果最优计划\(P\)已知,而由查询优化器生成的计划为\(\hat{P}\),如果基数估计产生错误的bound我们已经知道,那么这个bound是否也可以约束\(\hat{P}\)和\(P\)之间的开销差距。也就是说,我们是否能通过基数估计产生的错误的边界而得到生成的执行计划与最优计划之间的差距?
    • Q3:我们如何最大限度的减少基数估计的错误?
  • 上述问题在本文中会得到逐一的解答。

q-error的定义

  • 首先对选择性估计问题进行了一个明确的定义

    • 有一个关系\(R\),\(A\)是\(R\)的一个属性。\({x_1,x_2,\cdots,x_m}=\Pi_A(R)\)是\(A\)的所有无重复取值。此时频率密度可以由一个对偶\(<x_i,f_i>\)集合表示,其中\(f_i=\{\sigma_{A=x_i}(R),i\in [1,m]\}\)。选择性估计的任务就是通过函数\(\hat{f}\)近似这组键值对,并将\(f\)映射到(0,1)。
  • 给出了q-error定义:

    • 在数学中,常用范数来进行误差分析,如果实际值用\(b\)向量表示,估算值用\(\hat{b}\)向量表示,用 p-范数计算的误差为:
    \[||b-\hat{b}||=\sqrt[p]{(b_i-\hat{b_i})^p}
    \]

    比较常用的是2-范数和\(\infty-\)范数,2-范数的结果是向量的长度,即向量各元素平方和再开方,\(\infty-\)范数是所有向量元素绝对值中的最大值。通过\(\infty-\)范数可以推导出估计值\(\hat{b}\)的上下界分别为\(b_i\)加减\(\infty-\)范数的值。但是绝对误差上界在查询优化中通常不是那么有用,文中定义了另一个误差函数q-error。

    • 首先给出q范数的定义:
      \[||z||_Q=\begin{cases}\infty \quad z\leq 0\\\frac{1}{z} \quad 0<z\leq 1\\z\quad 1\leq z\\\end{cases}
      \]
    • 对于一个向量\(z\):
    \[||z||_Q=\max_{i=1}^m||z_i||_Q=\max_{i=1}^m(\max{(z_i,\frac{1}{z_i})})
    \]
    • 对于估计值\(\hat{b}\)和真实值\(b\),我们将q-error定义为:
      \[||\frac{\hat{b}}{b}||_Q
      \]

      通过Q范数的定义形式,我们可以进一步推导得:

      \[q=||\frac{\hat{b}}{b}||_Q=\max_{i=1}^m(\max{(\frac{\hat{b_i}}{b_i},\frac{b_i}{\hat{b_i}})})
      \]
    • 类似于\(\infty\)范式,我们也能够确定一个基于Q范数估计值的边界:
    \[(\frac{1}{q})f_i\leq \hat{f_i}\leq qf_i
    \]

    到此我们了解了什么是 q-error 以及它的形式化定义,那为什么论文采用 q-error 来表示估算误差呢?在论文的第三部分我们会看到,我们可以通过最小化 q-error 来最小化估算误差的传播,q-error 也能帮我们解决 “是否存在一个误差上界,只要优化器的估算误差在这个上界以内就可以保证选到最佳执行计划?” 这个问题。

最小化q-error能最小化误差传播

《On the Propagation of Errors in the Size of Join Results》表明 selectivity 估算误差会在 join 节点上指数级的放大,如果用 q-error 来表示估算误差,join 结点对 selectivity 估算误差的放大效果是怎么样的呢?

  • 为了寻找 n 个表\(\{R_1,R_2,\cdots,R_N\}\)join 的最佳执行计划,我们需要先对每个表做 selectivity 估算,论文中假设了一个没有 join 条件(笛卡尔积)的简单场景,所有的过滤条件都推到了各个表上,这些表的 join 表示为\(\sigma_{p_1}(R_1)\Join \cdots\Join \sigma_{p_n}(R_n)\),令\(x\)表示这 n 个表的一个子集,这个子集里面 join 结果集的大小可以表示为:
\[s_x=(\prod_{R_i\in{x}}f_i)(\prod_{R_i\in{x},R_j\in{x}}(f_{i,j}))(\prod_{R_i\in{x}}|R_i|)
\]
  • 其中:

    • \(f_i\)表示\(\sigma_{p_i}(R_i)\)的真是selectivity
    • \(f_{i,j}\)表示表示第 i 和 j 个表 join 的真实 selectivity,如果没有 join 条件(笛卡尔积)则\(f_{i,j}=1\)
    • \(|R_i|\)表示第 i 个表的真实结果集大小
  • 可以通过先计算 k 个表 join 的结果集公式,再计算新增一个表(k+1 个表)的 join 结果集公式来得到上面 n 个表 join 的结果集大小计算公式。

我们用\(\hat{f_i}\)表示\(\sigma_{p_i}(R_i)\)的selectivity估算值,在假设量表join的selectivity估算值没有误差,以及各个表结果集大小的估算没有误差的情况下,可以通过上述计算公式得到这些表join结果集大小的估算值为:

\[\hat{s_x}=(\prod_{R_i\in{x}}\hat{f_i})(\prod_{R_i\in{x},R_j\in{x}}(f_{i,j}))(\prod_{R_i\in{x}}|R_i|)
\]

利用\(\prod_{R_i\in{x}}\frac{f_i}{f_i}=1\)的事实,我们可以给\(\hat{s_x}\)做一个等价变换:

\[\hat{s_x}=(\prod_{R_i\in{x}}\frac{f_i}{f_i})(\prod_{R_i\in{x}}\hat{f_i})(\prod_{R_i\in{x},R_j\in{x}}(f_{i,j}))(\prod_{R_i\in{x}}|R_i|)
\]
\[\hat{s_x}=(\prod_{R_i\in{x}}\frac{\hat{f_i}}{f_i})s_x
\]
\[\hat{s_x}\leq{(\prod_{R_i\in{x}}{\max(\frac{\hat{f_i}}{f_i},\frac{f_i}{\hat{f_i}})})s_x}
\]

而单个值的\(f_i\)和它的估计值\(\hat{f_i}\)的q-error可以表示成\(\max{(\frac{\hat{f_i}}{f_i},\frac{f_i}{\hat{f_i}})}\)。上面join集结果告诉我们:如果要最小化估算误差在 join 结点上的传播,我们需要最小化每个表上 selectivity 估算的 q-error。

  • 得到的结论似乎在预期之中,因为直觉告诉我们,不管估算误差用什么数学公式计算,只要我们能够最小化基表的估算误差,就一定对最小化 join selectivity 估算误差有帮助,上面的证明过程把这一直觉严谨的推演证明出来了,并且告诉了我们缩小估算误差的方式是缩小 q-error 而不是缩小绝对误差(∞-范数)。

  • 不过值得注意的是,要最小化 join 误差,我们还需要最小化两表 join selectivity 和各个表结果集大小的估算误差,分别是\(f_{i,j}\)和\(|R_i|\)

可以计算q-error界限,估计误差在此界限内的计划均为最优计划

确定一个选择性估计的偏离范围,使误差在此范围内不会影响最优执行计划的生成,换句话说q-error 的上界值应该是多少,使得只要优化器的估算误差在这个上界以内就可以保证选到最佳的执行计划?

论文分别就星型连接、链式连接以及普通的树形连接给出了相应的 q-error 上界计算公式。下面不等式的右边就是每个表 selectivity 估算误差的上界

  • 星型查询:
\[||\frac{f_k}{f_k'}||_Q\leq\min_{i\neq{j}}\sqrt{||\frac{f_if_{0,i}|R_i|}{f_jf_{0,j}|R_j|}||_Q}
\]
  • 链式查询:
\[||\frac{f_k'}{f_k}||_Q\leq\min_{i\neq{j-1}}\sqrt{||\frac{f_if_{i,i+1}|R_i|}{f_jf_{j,j-1}|R_j|}||_Q}
\]
  • 树型查询:
\[||\frac{f_k'}{f_k}||_Q\leq\min_{i\neq{j},R{i'}-R_i,R{j'}-R_j}\sqrt{||\frac{f_if_{i,i'}|R_i|}{f_jf_{j,j'}|R_i|}||_Q}
\]

q-error 上界能进一步推导出代价估算的误差上界

估算代价可以分为两步:selectivity 估算和代价估算。前者计算出某个算子会产生多少条数据,后者根据算子的物理实现,综合 CPU、内存、网络、磁盘以及刚才 “产生多少条数据” 等因素给出一个综合的代价值。论文的 “3.3 Cost Bounds Implied by Q” 部分通过推理,得到了一个结论:\(C(\hat{P})\leq q^4C(P)\),selectivity 估算误差上界可以推导出 cost 估算误差的上界。

如何设计 selectivity 估算函数使其低于误差上界

论文 “4. BEST APPROXIMATION UNDER LQ” 部分详细介绍了直方图桶内等值查询和范围查询的 selectivity 估算方法,如这章节开头所说 “This section makes heavy use of math“,因为数学公式比较多,看起来会吃力一些。

假设我们要估算一个过滤条件 where col = x 的 selectivity,经过数学建模和一系列的推导,论文提出使用线性函数\(\beta + \alpha x\)来拟合直方图桶内等值查询 selectivity 估算的方法,范围查询可以由等值查询推导而来。论文在 "4.2 Approximation Algorithm" 中给出了\(\alpha\)和\(\beta\)的计算方法,下图中 \(x_i\) 是采样值,\(b_i\) 是实际的 selectivity:

![[Pasted image 20211115190054.png]]

如何构造直方图

论文在 ”5.3 Piecewise Approximation“ 中简单描述了如何构造直方图。构造直方图比较难的地方是确定直方图每个桶的上下边界,比如等深直方图通过固定桶的数量和限制落在这个桶中的数据量一样多来计算每个桶的上下边界。在上面小结的计算过程中我们观察到,一个桶中的数据量越多,线性拟合的估算误差 q-error 就越大,这就给我们构造直方图每个桶的上下边界提供了指导思想。只要我们固定估算误差 q-error,就能够计算出落在每个桶中的数据有哪些(可以二分查找),进而得到每个桶的上下边界,构造出完整的直方图。论文中这里没有再详细描述,它给的参考文献可以读一读:《[Smooth Interpolating Histograms with Error Guarantees](download (psu.edu))》。

最后

这篇论文后面还有不少实验数据来验证线性拟合和其他估算方式的 q-error 对比,可以看到线性拟合的 q-error 确实能够限制在比较小的范围内。

总体上这篇论文对误差估算的建模分析是值得我们学习的,q-error 更是给我们如何衡量估算误差,如何降低估算误差指明了方向,这个的意义挺大的。

——觉得有帮助给笔者点个关注点个赞呀_

——参考https://zhuanlan.zhihu.com/p/165959743

限制q-error,防止产生次优计划的更多相关文章

  1. Postfix配置Q&A

    原文地址:http://space.doit.com.cn/51460/viewspace-4943.html 在配置Postfix中遇到的一些问题及相关的解决方法,希望在遇到相同的问题时能起参考的作 ...

  2. 执行计划sql

    我准备开始分析并优化我的查询.在分析之前,我想到了一些问题. MS-SQL Server什么时候使用"Table Scan"? MS-SQL Server什么时候使用"I ...

  3. sql server 数据库优化--显示执行计划

      刚开始用SQL Server的时候,我没有用显示执行计划来对查询进行分析.我曾经一直认为我递交的SQL查询都是最优的,而忽略了查询性能究竟如何,从而对“执行计划”重视不够.在我职业初期,我只要能获 ...

  4. 安装HomeBrew 失败的解决方案(Error: Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core failed!)

    在安装HomeBrew(或者安装成功 执行相关指令)时遇到错误提示: Error: Failure while executing: git clone https://github.com/Home ...

  5. Running MYSQL 5.7 By Bash On Ubuntu On Windows:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

    root@PC-RENGUOQIANG:/usr/sbin# /etc/init.d/mysql start * Starting MySQL database server mysqld [ OK ...

  6. mysql basic operation,mysql总结,对mysql经常使用语句的详细总结,MySQL学习笔记

    mysql> select * from wifi_data where dev_id like "0023-AABBCCCCBBAA" ; 1.显示数据库列表.show d ...

  7. Python开发入门与实战14-基于Extjs的界面

    14. 基于Extjs的界面 上一章我们实现了一个原生的html例子,本章我们将采用Extjs实现界面的展现,来说明MVC模式下我们是怎么考虑界面与业务层的关系的. 14.1. 引用Extjs目录 首 ...

  8. Python开发入门与实战13-基于模板的界面

    13. 基于模板的界面 本章我们将继续基于库存的简单例子来阐述如何在python django中体现MVC的架构,根据djangobook说明: M:数据存取部分,由django数据库层处理,本章要讲 ...

  9. VS2013使用rtklib中需要注意的一些问题(编译)

    最近因为项目需要需要对rtcm数据进行解码,rtklib提供了很多底层的函数,准备直接输出标准DLL的方式供C#调用.下面把项目中引用rtklib源码需要注意的地方记录下. 1. 首先在vs2013中 ...

随机推荐

  1. 数据结构与算法——克鲁斯卡尔(Kruskal)算法

    目录 应用场景-公交站问题 克鲁斯卡尔算法介绍 克鲁斯卡尔算法图解 克鲁斯卡尔算法分析 如何判断回路? 代码实现 无向图构建 克鲁斯卡尔算法实现 获取一个点的终点解释 应用场景-公交站问题 某城市新增 ...

  2. Java String的探讨

    关于String相关内容的学习,历来都是Java学习必不可少的一个经历. 以前一直想要好好总结一下String的相关的知识点,苦于没有时间,终于在今天有一个闲暇的时间来好好总结一下,也希望这文章能够加 ...

  3. Android系统编程入门系列之应用间数据共享ContentProvider

    内容提供者ContentProvider与前文的界面Activity.服务Service.广播接收者BroadcastReveiver,并列称为Android的四大组件,均是需要自定义子类继承上述组件 ...

  4. I-Base62

    I - Base62 PS:一个任意进制转换的大数问题 传送门:Base62 短除法原理: 20(10进制) => 202(3进制) 20 = (2 * 3 ^ 2 + 0 * 3 ^ 1 + ...

  5. 【UE4 C++】DateTime、Timespan 相关函数

    基于UKismetMathLibrary DateTime 相关函数 Timespan 运算操作相关函数见尾部附录 /** Returns the date component of A */ UFU ...

  6. UltraSoft - Beta - Scrum Meeting 1

    Date: May 17th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 维护Beta阶段文档 Liuzh 前端 增加删除操作按钮 Kkkk 前端 查询增加 ...

  7. 使用logstash的input file filter收集日志文件

    使用logstash的input file filter收集日志文件 一.需求 二.实现步骤 1.前置知识 2.编写pipeline文件 3.Input 中 file 插件的部分参数解释: 4.启动l ...

  8. 2021.8.5考试总结[NOIP模拟31]

    暴力打满直接rk3? T1 Game 想了一万种贪心和两万种$hack$. 可以先用最显然的贪心求出最高得分是多少.(从小到大用最小的大于$b_i$的$a$得分) 然后用一棵权值线段树维护值域内$a$ ...

  9. STM32的I2C框图详解及通讯过程

    STM32 的I2C 特性及架构 如果我们直接控制STM32 的两个GPIO 引脚,分别用作SCL 及SDA,按照上述信号的时序要求,直接像控制LED 灯那样控制引脚的输出(若是接收数据时则读取SDA ...

  10. 从0到1搭建自己的组件(vue-code-view)库(上)

    0x00 前言 本文将从结构.功能等方面讲解下项目 vue-code-view 的搭建过程,您可以了解以下内容: 使用 vue cli 4从0搭建一个组件库及细致配置信息. 项目的多环境构建配置. 项 ...