数据库原理(六)查询处理和优化

概述

  • 查询处理:从查询语句出发,到获得查询结果

  • 查询优化:DBMS对描述性语言表达的查询语句进行分析,为其确定合理、有效的执行策略和步骤的过程

    • 查询优化是查询处理的重要一环,尤其对于关系数据模型 为什么呢?
    • 不能片面追求“最优”
  • 查询语句处理:解释、翻译

  • 解释执行:不生成中间结果,优化占据执行时间

    编译执行

  • 编译执行:预编译,优化不会占用执行时间

    解释执行

    • 常见,频繁使用,编译可提高性能
  • 代数优化、物理优化、规则优化、代价估算优化

代数优化

相关信息

  • 目的:减少执行开销
  • 原则:尽量减小查询过程中间结果的大小
  • 不涉及存取路径
  • 选择、投影操作减小关系大小
  • 连接、笛卡尔积、并操作易生成大的中间结果
    • 关系型数据库不可避免连接操作
  • 做法:
    • 先做选择、投影;
    • 先做小关系连接;
    • 找出公共表达式,避免重复计算

常用规则

  1. σ c 1 A n d c 2 … A n d c n ( R ) ≡ σ c 1 ( σ c 2 ( … ( σ c n ( R ) ) …   ) ) \sigma_{c_1Andc_2\dots Andc_n}(R)\equiv\sigma_{c_1}(\sigma_{c_2}(\dots(\sigma_{c_n}(R))\dots)) σc1Andc2Andcn(R)σc1(σc2((σcn(R))))

    • 左边效率更高,只需要调入一次;右边需要(n-1)*2,(一次读一次写)
  2. σ c 1 ( σ c 2 ) ≡ σ c 2 ( σ c 1 ) \sigma_{c_1}(\sigma_{c_2})\equiv\sigma_{c_2}(\sigma_{c_1}) σc1(σc2)σc2(σc1)

    • 可使用第一个规则证明
  3. ∏ l i s t 1 ( ∏ l i s t 2 ( … ( ∏ l i s t n ( R ) ) …   ) ) = ∏ l i s t 1 ( R ) \prod_{list_1}(\prod_{list_2}(\dots(\prod_{list_n}(R))\dots))=\prod_{list_1}(R) list1(list2((listn(R))))=list1(R)

    l i s t 1 ⊆ l i s t 2 ⊆ ⋯ ⊆ l i s t n list_1\subseteq list_2\subseteq\dots\subseteq list_n list1list2listn

  4. ∏ A 1 , A 2 , … , A n ( σ c ( R ) ) ≡ σ c ( ∏ A 1 , A 2 , … , A n ( R ) ) \prod_{A1,A2,\dots,An}(\sigma_c(R))\equiv\sigma_c(\prod_{A1,A2,\dots,An}(R)) A1,A2,,An(σc(R))σc(A1,A2,,An(R))

    A t t r ( C ) ⊆ A 1 , A 2 , … , A n Attr(C)\subseteq{A1,A2,\dots,An} Attr(C)A1,A2,,An

  5. R    J N    S = S    J N    R R~~ JN~~S=S~~JN~~R R  JN  S=S  JN  R

  • J N JN JN表示连接操作
  1. σ c ( R    J N    S ) = ( σ c ( R ) )    J N    S        A t t r ( c ) ⊆ A t t r ( R ) \sigma_c(R~~JN~~S)=(\sigma_c(R))~~JN~~S~~~~~~Attr(c)\subseteq Attr(R) σc(R  JN  S)=(σc(R))  JN  S      Attr(c)Attr(R)
  • 属性c可以在S中
  1. σ c 1   A N D   c 2 ( R   J N   S ) ≡ ( σ c 1 ( R ) ) J N ( σ c 2 ( S ) ) \sigma_{c1~AND~c2}(R~JN~S)\equiv(\sigma_{c1}(R))JN(\sigma_{c2}(S)) σc1 AND c2(R JN S)(σc1(R))JN(σc2(S))

    A t t r ( c 1 ) ⊆ A t t r ( R )        A t t r ( c 2 ) ⊆ A t t r ( S ) Attr(c_1)\subseteq Attr(R)~~~~~~Attr(c_2)\subseteq Attr(S) Attr(c1)Attr(R)      Attr(c2)Attr(S)

  2. 规则8

    • 连接后再投影可以转换为分别投影之后再连接
  3. 规则9

    • 选择操作可先于并 交 差操作,类似于分配律
  4. 规则10

    • 选择操作可先于并 交 差操作,类似于分配律
  5. 规则11

    • 对于连接运算,可能出现S与T之间无连接条件的情况,此时的连接运算成为迪卡尔乘积

基本步骤

  1. 以SELECT子句对应投影操作,以FROM字句对应迪卡尔乘积,以WHERE子句对应选择操作,生成原始查询树

    原始查询书

  2. 应用变换规则2)、6)、7)、9)、10),尽可能将选择条件移向树叶方向。

  3. 应用连接、迪卡尔乘积的结合律,按照小关系优先做的原则,重新安排连接(笛卡尔乘积)的顺序。

  4. 如果笛卡尔乘积后还须按连接条件进行选择操作可将两者组合成连接操作。

  5. 对每个叶节点加必要的投影操作,以消除对查询无用的属性。

适用范围

  1. 上述讨论适合于非嵌套查询
  2. 嵌套查询较为复杂,分两种情况
    • 嵌入的查询块与上层查询无关
      • 从最底层开始,使用上述步骤,逐层计算
    • 迁入的查询块与上层查询有关
      • 代入法
      • 尽可能使用部分选择:类似编译原理中的代码短路

小结

  • 代数优化不涉及存储路径
  • 只会在操作次序和组合上进行调整,相对粗糙

依赖于存储路径的优化

选择操作的实现和优化

  • 实现方法:顺序扫描、散列、索引
  • 启发式规则
    • 对于小关系直接顺序扫描
      • 索引多次输入输出,可能减缓效率
    • 若无索引可用,或估计选取的元组数占关系的比例较大,且有关属性无簇集索引,使用顺序扫描
    • 对于主键,优选选用主键的索引
    • 对于非主键,选取元组数占关系的比例较小,可以使用无序索引;否则使用簇集索引或顺序扫描
      • 无序索引:也称二次索引,相对于簇集索引
    • 对于范围条件,先通过索引找到范围的边界,再通过再通过索引的顺序集沿相应方向搜索,如中选的元组数在关系中所占比例较大,宜采用簇集索引或顺序扫描
    • 对于使用AND连接的选择条件
      • 优先选用多属性索引
      • 若有多个可用的次索引,使用预查找,再做其余条件检查
      • 个别条件可用上述规则之一,先优化,再使用其他条件
      • 顺序扫描
    • 对于使用OR连接的选择条件
      • 只能按其中各个条件分别选出一个元组集,再求这些元组集的并
      • 在OR连接的诸条件中,只要有一个条件无合适的存取路径,就只能用顺序扫描

选择操作的实现和优化

连接开销较大,为优化重点,此处主要考虑二元连接

  • 实现方法:嵌套循环、索引匹配、排序归并、散列连接

  • 嵌套循环

    嵌套循环1

    • 关系R与S进行连接操作,最原始的办法是取R的一个元组,与S的所有元组比较,凡是满足连接条件的元组就进行连接并且作为结果输出。然后再取R的下一个元组,和S的所有元组比较,直到R的所有元组比较完为止。

      嵌套循环2

    • 事实上,关系是以物理块为单位取到内存,设R和S各有一缓冲块, P_R为R的块因子(每块中所含的元组数)。则R每次I/O取P_R个元组,可改进上述算法,使S扫描一次可以与R的P_R个元组比较,那么S的扫描次数为b_R=[n/P_R] 。

    • 应该将占用物理块少的关系作为外关系

  • 索引匹配法

    • 若内关系上有合适的存取路径(连接属性上的索引散列等),可以避免内关系上的顺序扫描,以减少I/O次数
    • 当每次循环所选的匹配元组数在内关系中占有较大比例(例如超过15%)时,用无序索引甚至还不如用顺序扫描的方法
    • 内关系的连接属性上有簇集索引时,索引对减少连接所需I/O次数的作用最明显
  • 排序归并

    • 如果R和S按连接属性排序,可按序比较R.A和S.B以找出匹配元组
    • 效率受重复度影响 → \rightarrow 等值记录越多,性能越差,最差会退化到嵌套循环
    • 数据集需要排序
  • 散列连接

    • 连接属性R.A和S.B应具有相同的值域,用相同的散列函数,把R和S散列到同一散列文件中。符合连接条件的元组必然在同一桶中。只需把桶中的匹配元组取出即可获得连接结果。
      • 注意:同一桶中的元组未必都满足连接条件
    • 关键在于建立一个供连接用的散列文件。 建立散列文件需要对R、S各扫描一次,且关系R和S一般不会对连接属性进行簇集。故而,每向散列文件加入一个元组,都需要一次I/O操作。
    • 减少IO次数:可以在桶(散列文件)中不填入R、S的实际元组,而是代之以元组的tid,从而大大的缩小散列文件,使其有可能在内存中建立,而仅需对R、S各扫描一次。
    • 扫描R和S时,取出PA®、PB(S),附在相应的tid后,连接时以桶为单位,按PA®=PB(S)找出匹配元组的tid对
      • A=B 推出 h(A)=h(B),但不一定有:h(A)=h(B) 推出 A=B
  • 启发式规则

    • 两个关系都已按连接属性排序,则优先用排序归并法;两个关系中已有一个关系按连接属性排序,另一个关系较小,也可先对未排序关系按连接属性排序,再用排序归并法。

    • 两个关系中有一个关系在连接属性上有索引(特别是簇集索引)或散列,可以另一关系为外关系,顺序扫描,并利用内关系上的索引或散列寻找其匹配元组,以代替多遍扫描。

      • 簇集索引在内关系上
    • 不具备上述条件且关系较小,可用嵌套循环法。

    • 不具备1,2,3规则,可用散列连接法。

投影操作的实现和优化

  • 一般与选择、连接同时进行,无需附加的I/O开销。
  • 若投影属性集中不包含主键,则投影结果中可能出现重复元组。
  • 消除重复元组可以用排序或散列等方法。
    • 散列法:将投影结果按某一属性或多个属性散列成一个文件,当一个元组被散列到一个桶中时,可检查是否与桶中已有元组重复。
    • 排序法:排序之后去重

集合操作

  • 常用:笛卡尔积、并、交、差
  • 笛卡尔积:将两个关系的元组无条件地互相拼接,一般用嵌套循环法实现,做起来很费时,结果要比参与运算的关系大的多
  • 设关系R、S并兼容,对R、S进行并(交、差)操作,可以先将R和S按同一属性(通常选用主键)排序,然后扫描两个关系,选出所需的元组。
  • 散列法:将关系R散列到一个散列文件中,再将S散列到同一文件中。同时检查桶中有无重复元组。对于并,不再插入重复元组;对于交,选取重复元组;对于差,从桶中取消与S重复的元组。

组合操作

  • 多个操作组合起来同时进行,可提高效率
  • 假设连接用嵌套循环法,R为外关系,S为内关系,R的选择、投影可在扫描R时执行,S的选择、投影可在首次扫描S时执行,并将选择、投影的结果存入临时文件,之后各轮只需扫描临时文件即可。
  • 最后一个投影操作,可在生成连接结果的同时进行。

优化小结

  • 静态优化:只利用统计数据,在执行前进行优化
  • 动态优化:在查询执行时进行优化,用实际执行结果估算代价
    • 符合实际
    • 每次执行时都要进行优化,不适合编译实现,增加执行时间
    • 需要等待中间结果,增加等待时间和数据的相关性,不利于并行
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值