How Good Are Query Optimizers, Really?

目录

  • 动机
  • 问题
  • 贡献
  • 背景
  • 相关工作
  • 基数估计
  • 成本模型
  • 连接顺序
  • 结论
  • 未来

动机

  1. 连接顺序对查询至关重要
  2. 基数估计产生误差,过度依赖基数估计导致查询性能不太好
  3. 成本模型对查询性能影响

问题

  1. 基数估计有多好,在什么时候才会估计不好,进而导致查询变慢?
  2. 准确的成本模型对查询优化有多重要?
  3. 枚举计划的空间有多大?

贡献

  1. 引入JOB,使用复杂真实查询集和数据集IMDB
  2. 首次使用真实数据集和查询集进行端到端研究
  3. 实验侧重内存场景
  4. 单个优化器组件实验
  5. 评估基数估计、成本模型、计划枚举算法对查询性能的影响,进而为查询优化的设计提供指导,避免极差的计划。

背景

  1. 计划枚举技术由穷举动态规划结合启发式方法进行设计
  2. 基数估计、成本模型作为输入,指导动态规划
  3. 若基数估计、成本模型足够准确,优化器给出的计划就越好。
  4. 但传统数据库的基数估计是基于简单的假设、独立性、一致性
  5. 所以,对于真实世界的数据集容易估计错误,最终导致次优计划

相关工作

  1. 现象:忽略基数估计研究,专注于搜索空间探索或者孤立研究基数估计,不统揽全局地研究;解决:评估所有组件在真实数据集和查询集中,对端到端的查询性能影响;细节:采用PG数据库、IMDB数据集、JOB基准
  2. 现象:传统基准虽然已经评估过对查询性能的影响,但并不是很好的基准;原因:基准采用简单性假设、独立性、一致性、包含原则,但真实世界数据集是相关性、非均匀分布;传统基准例子:TPC-H、TPC-DS、SSB;解决:使用IMDB、JOB
  3. IMDB,内容:电影数据集,包含演员、导演、制作公司等信息、非商业用途;转换:采用imdbpy将数据集转换为包含21个表的数据库,最大表演员表、电影表;
  4. JOB基准,内容:基于IMDB数据库构造;特点:关注连接顺序,将查询设计为3-16个连接数量,平均8个连接数量;例子:
    How Good Are Query Optimizers, Really?_第1张图片
  5. JOB,形式:每个查询由select-project-join组成,33个查询模板,每个模板有2-6变量,总共113个查询;注意:一方面,由于基表谓词选择性,相同查询模板的变体有不同的最佳计划,差异大,另外实际查询中还有诸如like等谓词更加复杂,差异更大,另一方面,并没有取极端相关属性进行实验,或者有意不包括复杂谓词;其他:JOB省去聚合操作,且使用MIN,避免出现记录条数巨大的结果集。
    How Good Are Query Optimizers, Really?_第2张图片
    其中实线代表主键:外键=1:n,箭头指向主键;虚线代表外键:外键连接=n:m
  6. PG,优化器内容:动态规划、左深、浓密、一般谓词按基数估计(直方图也叫分位数统计、常见值频率、不同值个数也叫域)、复杂谓词按经验估计、简单性假设(一致性:除了最常见值,其余值都处理为相同个数;独立性:关于属性的谓词独立;包含原则:较小连接域属于较大连接域)公式如下:
    在这里插入图片描述
    其中dom代表不同值个数计算函数,T代表表达式
  7. PG,查询引擎:确定物理运算符、访问方式(表扫描、索引)、连接方式(嵌套循环{有无索引}、内存散列、聚合连接)、排序可以溢出到磁盘;执行解释:Volcano-style;流程:数据集加载到数据库、基数提取(收集信息,如explain、analyze等命令)、一系列中间结果基数、基数注入(允许各种系统的基数估计)、评估对查询性能的影响
  8. 实验配置,单核运行、大内存、重新设置操作符内存限制、重新设置系统缓存限制、重新设置数据库缓存、重新设置geqo=18(超过此数值,采用遗传算法或者贪婪算法)

基数估计

  1. 基数估计,重要性:保证成本模型的准确性,进而对找到好的连接顺序至关重要;不足:有时会出现错误估计,导致查询计划糟糕,进而查询性能缓慢。
  2. 基表估计,指标:q-error,与真实基数的相对误差,提供有界误差;实验图:
    How Good Are Query Optimizers, Really?_第3张图片
    其中中位数估计是接近最优值,而其他却很差。
    如复杂谓词评估,通常采用随机抽样,但经过实验发现,超过2个错误后,真实选择性极地,若出现0元组情况,则通常按特殊方法估计(如:神奇数字)。而直方图估计,会更加糟糕,且不能检测一些相关性。
  3. 连接估计,原因:连接后的中间结果很难估计;现象1:且越多连接,q-error越大,误差可达到1000倍,呈指数级增长,界限越宽;实验如图:
    How Good Are Query Optimizers, Really?_第4张图片
    现象2:对于多连接,趋向于低估;现象3:DBMS A估计更趋向中值;推测:A有些对于多连接这种情况,采用设置阻尼因子,处理多个谓词,并不是完全独立,而是向上微调,当成整体选择,多个谓词是有一定关联;PG的结论:基数估计是简单性假设,无相关性设置,错误数量级大;相关推测:基数估计差的某些系统,不一定查询性能也差,通常还需要取决于如何使用估计值,信任与否,自适应与否。
  4. 基数估计应用TPC-H基准,实验结果:
    How Good Are Query Optimizers, Really?_第5张图片
  5. 连接估计错误的根本原因:是否是错误估计的不同计数,采用真实的不同计数进行对照实验,发现真实的不同计数反而更加低估,而这是由于之前被低估的不同计数反而导致更高的估计,更接近真实,负负得正。但这不能运用到分析和修复查询优化器问题中,就好比修复一个查询,必须破坏另一个。
    How Good Are Query Optimizers, Really?_第6张图片
  6. 何时糟糕的基数估计导致查询性能缓慢: 由于索引类型和数量影响后续搜索空间,所以,当数据库设计更多的索引时,会导致错过最优计划,导致查询性能缓慢。
  7. 评估不同系统的基数估计:相对真实基数,其查询性能快慢程度占比
    How Good Are Query Optimizers, Really?_第7张图片
  8. PG基数估计评估,情况:对于估计值超过合理查询时间,则引入嵌套循环连接(无索引),更进一步,是由于在成本模型上的比较,嵌套循环连接估计值小于散列, 但散列复杂度=n,嵌套循环=n平方,那么估算就相当危险,极易产生错误估计。解决:禁用嵌套循环,但并不禁用索引嵌套循环。实验结果:
    How Good Are Query Optimizers, Really?_第8张图片
  9. PG,新的情况:虽然没有超时,但依然慢10倍以上;原因:低估导致内存较小,哈希表较小,冲突过大,性能差;解决:根据实际存储行数来调整哈希表大小。
  10. 总结:纯粹基于成本,不考虑基数估计的不确定性和不同算法选择复杂性,会导致糟糕计划;提出:应该选择更健壮算法,以及自适应调整参数运行时间,而不依赖基数估计。
  11. 基数低但计划好,现象:糟糕的基数估计,但嵌套循环连接被禁用,重新散列被启用,散列性能大大优于嵌套;原因:只有主键索引,无外键索引,采用全表扫描,这样不同的连接顺序对性能的影响减小 ,且性能接近于基于真实基数的性能;推测:基数估计足够好,就可以避免灾难性连接顺序决策。
  12. 添加外键索引进行对照实验,如图;注意:并不是索引越多,性能下降,在总体性能上,应该是提高的,但查询优化难做。
    How Good Are Query Optimizers, Really?_第9张图片
  13. 交叉连接相关性,前沿:存在相关性谓词情况下,估计中间结果的基数;定义:存在相关性谓词,特别是存在与不同表中的列值进行连接;例子:ROX(ROX: run-time optimization of XQueries),手工设计分区索引,得到可用的访问路径,对查询优化性能提高;结论:这只是一个特例,直接设计了一个由交叉连接谓词来设计分区索引,并不是通用方案;展望:可以关注交叉连接相关性,如何减少中间结果过大的基数估计,此领域涉及物理设计、查询优化、查询执行相互作用。

成本模型

  1. 成本模型,作用:指导从搜索空间确定连接顺序;内容:PG的成本模型复杂,主要是基于磁盘;实验流程:建立在PG上,观察成本模型与查询运行性能联系,然后,再比较两种不同的成本模型(基于内存和简单函数的成本模型)。
  2. 成本模型,具体内容:CPU、I/O与权重结合,进一步讲,是访问磁盘页的数量(随机、顺序访问均可)以及内存中数据量的加权和,再将每一步成本相加得到总成本,总成本再与手工设计的权值相乘,得到查询计划的成本估算值。
  3. 成本模型,文档:没有明确方法指导理想的数值(上文中涉及到的CPU、I/O参数之类的),换句话说,只能依靠数据库管理人员按照经验进行设置,不过大多数管理人员会使用默认值,但是,默认值往往 是次优的;例子:处理元组比页面读取元组便宜400倍,但现代数据库都是大内存的,虽然页面访问成本还在(缓冲区开销),但大大缩小了I/O和CPU成本的差距);展望:提出了采样、机器学习方法对成本模型进行设定。
  4. 成本模型与运行时间,优点:给定基数情况下,预测哪一个计划较快;预测误差:在这里插入图片描述
    实验如图:
    How Good Are Query Optimizers, Really?_第10张图片
    分析:一方面,其中c、d代表重新设置了成本模型的CPU参数后的结果,明显提高了与真实时间的相关性,但真实基数与估计基数的差异仍然存在,同时c出现了震荡现象,有异常值,在成本很高的情况下,时间很低,正对应了上文提出了的错误基数估计反而出现好的计划(负负得正);另一方面,预测误差也下降了。
  5. 探索,内容:复杂成本模型(磁盘查找和读取速度、CPU处理成本)在内存中是否有必要?方法:定制了一个基于内存的简单成本函数,不涉及I/O,只关心处理元组数量;公式:
    How Good Are Query Optimizers, Really?_第11张图片
    其中使用此成本函数实验如e、f所示,能够准确预测时间,且对真正基数而言的成本函数,也是一样,但使用真正基数与估计基数横向对比,改变就相当大;结论:基数估计比成本模型更加重要。

连接顺序

  1. 定义:计划枚举算法;常用 :穷举(Dynamic programming
    strikes back),( Counter strike: Generic top-down join enumeration for hypergraphs)、启发式(Heuristic and randomized optimization for the join ordering problem),(Query simplification: graceful degradation for join-order optimization);搜索空间:由不同数量候选解构成;目的:在搜索空间中采用算法较快找到好的计划。
  2. 流程特点:采用任意基数估计,充分探索空间,由于本文使用的查询含有大量连接,就先不执行;方法:使用估计基数。再使用真实基数计算成本,来预测时间,成本误差与基数误差相比极小;成本模型:上文中设计的简单成本函数;目的:在不执行所有计划的情况下,比较许多计划。
  3. 算法:动态规划、quickly(Join order selection - good enough is easy),其中quickly进行可视化不同连接顺序的成本;quickly内容:随机挑选连接边,直到所有关系被连接,每次生成一个正确但慢得查询计划;实验:对每个查询运行算法10000次,获得分布图,使用动态规划和真正基数获得最优计划;如图:
    How Good Are Query Optimizers, Really?_第12张图片
    分析:(1)最慢计划或者中间成本计划都比最优计划高几个数量级,说明连接顺序重要性(2)且PK并不能提高性能,但PK+FK可以(3)比最佳计划高1.5倍的计划占比44%(无索引)、39%(PK)、4(PK+FK)(3)最佳与最差之间分布宽度,101倍(无索引)、115倍(PK)、48120(PK+FK)
  4. 限定搜索空间,树形状:浓密树、左深、右深、之字
  5. 连接类型限制,不同连接类型,对于不同的树形状,约束不同;约束:散列连接——右深(从每个关系中创建哈希表,执行右深,再流水线探测)、散列——左深(根据中间连接结果构建新的哈希表)、散列——之字(是左深和右深超级集合,每个连接操作符必须有一个基本关系作为输入)、索引嵌套循环(以连接的左孩子为标准,在右孩子的索引中查找对应元组,且右孩子是基表)
  6. 实验,使用真正基数,呈现三种树结构的最优计划成本,如图:
    How Good Are Query Optimizers, Really?_第13张图片
    分析:之字最好,左深次之,右深糟糕。
  7. 启发式算法:动态、随机、贪婪GOO(A new heuristic for optimizing large queries),其他了解索引的启发式方法(Polynomial heuristics for query optimization)、给定穷举法(Dynamic programming strikes back)( Counter strike: Generic top-down join enumeration for hypergraphs);实验如图:
    How Good Are Query Optimizers, Really?_第14张图片

分析:由于基数估计错误,引入了估计误差将大于试探法导致更大性能损失。

结论

  1. 用于基数估计的整个表系统预测能力更好(相比单表、单列)
  2. 现有仍是简单性假设,应对连接交叉相关性还不足够。目前研究方向为基于连接样本(Selectivity and cost estimation for joins based on random sampling)、草图(Sketches for size of join estimation)、图形模型(Lightweight graphical models for selectivity estimation without independence assumptions)、采样(End-biased samples for join cardinality estimation)、相关样本(CS2: a new database synopsis for query estimation)。对于多连接(On the propagation of errors in the size of join results)还应继续探究。
  3. 连接交叉相关性利用查询反馈,如LEO(LEO -DB2’s learning optimizer),但需设计新的物理数据库、访问路径。
  4. 不但选择预期成本较低的计划,还会考虑到稍快计划的高风险(基于估计分布),这样基数估计错误的影响会大大减小。目前研究方向:基数估计(Preventing bad plans by bounding the impact of cardinality estimation errors)与成本模型( Towards a robust query
    optimizer: A principled and practical approach)结合。
  5. 查询更加健壮:连接动态切边、散列与排序间改变、顺序扫描与索引查找间切换、分组和分区实际数量改变聚合策略等减小成本错误估计的影响。
  6. 成本模型改进的影响小于基数估计,内存中的成本模型(Predicting query execution time: Are optimizer cost models really unusable? )已经足够预测
  7. 计划枚举器算法:随机优化(join order selection - good
    enough is easy)、搜索空间可视化(The Picasso database query optimizer visualizer),其物理设计和访问路径月丰富,好的查询计划就越少。
  8. 查询优化未解决( Is query optimization a solved problem?)
  9. 评估查询质量(1)Testing cardinality estimation models in SQL
    Server(2)Testing the accuracyof query optimizers(3)R* optimizer validationand performance evaluation for local queries(4)Plan spaceanalysis: an early warning system to detect plan regressionsin cost-based optimizers

未来

  1. 改进估算方法
  2. 运行与查询优化器交互
  3. 研究分布式数据库与磁盘上数据库是另一个挑战(本文基于内存)
    本文是对《How Good Are Query Optimizers, Really?》进行阐述。

你可能感兴趣的:(数据库内核开发,大数据,数据库,人工智能,机器学习,postgresql)