本文已收录到:CMU数据库系统学习笔记 专题
视频与PPT
视频:https://www.bilibili.com/video/BV1qR4y1W7v6?spm_id_from=333.880.my_history.page.click
为什么要引入优化器?
因为SQL语句是声明式的,只说了要什么答案,中间的过程没有定义,也就是执行计划是没有指定的。我想要A JOIN B,程序员不用去关心是A JOIN B还是B JOIN A算出来的。这些具体的东西由执行计划决定。
关于执行的两个流派
一个是认为应该由数据库系统替程序员优化;另一个流派认为应该由程序员自己优化。这两个流派直到今天也在争论。
就我们的课程来说,如果我们选择由数据库系统替程序员优化,那么… …请继续往下看
选择由数据库系统帮助优化
面临我们选择的依然会有两种方式:
基于启发:
例如数据库系统会去探查我们的列上面有没有索引,如果有的话就直接走索引。但是数据库系统不会去再详细的看这列的统计信息,他只关心基础信息,有或者没有。
基于代价:
估计多个查询计划的代价,进行比较,选择最小的代价。——前提是需要知道数据,知道数据量才知道时间。
现在大多数数据库以上两种流派都有实现。
体系结构概述
逻辑计划与物理计划
逻辑计划:给SQL程序员用的,基于关系模型。
物理计划:定义具体的执行方式,例如数据库系统里的算子,hash join,走索引还是走扫描?根据具体数据情况选择具体的物理算子。
查询优化是一个很难的问题
如果你很精通查询优化,那么你会拿到会高的薪水。IBM在2000年试图用人工智能来协助纯人工来优化查询,但是人工智能有个问题——不可解释性。很多时候人工智能告诉的结果使人摸不着头脑,不知道怎么得出来的。后来IBM在数据库系统中关闭了这个人工智能插件。
近些年,IBM又开始研究人工智能优化问题了… …
关系表达式的等价优化
两个关系表达式等价的话,他们输出的结果集是一样的。
直观来看,是先连接再筛选然后再投影输出。但是我们可以经过改造,谓词下推。先筛选再连接,达到了更高效的目的。
更多等价:
多条件谓词拆分。
等价拆分。
inter join符合交换律、结合律。多表join有4的n次方种执行方式,这个范围巨大。
投影输出。提前物化(干掉不打算输出的列),晚物化(不管列,我只对id做join,最后你再根据id去找数据列)
逻辑计划的优化
其实就是单纯的计划改写,数据库系统并不知道那种计划更好,更快,因为它没有代价模型。它只能根据你定义好的改写规则去把逻辑计划改写。
原先的查询计划:
改写后的查询计划:把谓词打散成三个谓词
谓词尽量往下推,越接近底层越好。
不要让无用的列翻上去:
嵌套子查询
重写
把子查询和外面的查询整合成一个查询。例如下面用户使用了带有EXISTS谓词的子查询,但是仔细一看他就是想连接两个表,然后做筛选而已。不如改写成一个SQL语句。这样可以生成一个高效的执行计划。
解耦
解耦,将子查询拿出来提前执行。
例如下面这个,谓词中带有子查询
上面这种子查询,因为数据是一个死数,可以先将其写入到临时表中,外面的查询用临时表中的数据去查。这样可能是一种高效的方案。
表达式重写
谓词重写,让谓词本身变得更高效。
例1:
例2:
例3:
有关代价的问题
需要在同一个数据库系统中比较。代价有下列几种:
物理代价
估算需要多少物理CPU计算、高速缓存misses、内存开销、预取开销等。与具体硬件有关,换个硬件代价数值就会变化。
经常出现在数据库一体机上。非常详细的知道运行这个计划需要多少周期,多少IO。微软sqlserver运行在Windows上,操作系统会对硬件有感知。一般开源数据库做不了这些。
逻辑代价
针对每个算子计算他们的开销。
算法代价
比较细的估计了算子本身的开销,算子实现的算法开销。
磁盘开销
其实磁盘开销才是最大的开销,CPU、内存的开销可以忽略不计。重点需要考虑磁盘开销。
来看几个数据库系统的代价模型
postgres数据库代价模型:
他们使用认为从内存中读取数据是从磁盘中读取数据的400倍。
他们认为顺序IO读取要比随机IO读取快4倍。
那么为什么呢?答:没有为什么,这是一个魔法数字,开发数据库系统的人在开发的时候在大多数机器上测试出来的比值关系。
就比如上你中午的订单量是晚上的4倍,为什么呢?没有为什么,每天就是这样。——这就是魔法数。
这个数字能改吗?比如我的电脑可能内存是磁盘的800倍。
答:别动,postgres的手册说明了。你很有可能一动这个数,后面无数的计划全部乱套了。甚至开发数据库系统的人也不知道是为什么。。就是这么魔法
下面看下DB2的代价模型:
DB2认为:
- 数据本身的特点跟开销有关系。
- 跟硬件的环境配置有关系。
- 代价大小跟存储器有关系。
- DB2如果部署成分布式数据库,还跟网络有关系。
- 跟排序缓存有关系。
- 跟并发处境有关系。数据库运行了多久,他的耗时都不一样。
- 与锁的数量和情况有关系。
从这里可以看出,商业数据库跟开源数据库是有区别的。考虑的要多得多。PT数据库是开源中比较优秀的数据库了,还比不上商业数据库。