数据库系统理论 -- 关系查询处理和查询优化

本篇文章会先介绍数据库的查询处理,然后介绍数据库的查询优化。其中查询优化分为代数优化物理优化。代数优化是指关系表达式的优化,物理优化是指通过存取路径和底层操作算法的选择进行优化。

查询处理

  • 查询分析
  • 查询检查
  • 查询优化
  • 查询执行

查询分析

对查询语句进行扫描,进行词法分析和语法分析。

  • 词法分析:MySQL 会根据你输入的字符串识别出关键字出来,构建出 SQL 语法树,这样方便后面模块获取 SQL 类型、表名、字段名、 where 条件等等。
  • 语法分析:根据词法分析的结果,语法解析器会根据语法规则,判断你输入的这个 SQL 语句是否满足 MySQL 语法。

查询检查

对合法的查询语句进行语义检查,即根据数据字典中有关的模式定义检查语句中的数据库对象,如关系名,属性名是否存在和有效。如果是对视图的操作,则要用视图消解方法对视图的操作转换成对基本表的操作。还要根据数据字典中的用户权限和完整性约束定义对用户存取权限进行检查。如果该用户没有相应的访问权限或者违反了完整性约束,就拒绝该查询。

查询优化

代数优化,物理优化

查询执行

根据优化器得到的执行策略生成查询执行计划,由代码生成器生成执行这个查询计划的代码,然后加以执行,回送查询结果。

查询操作几种常见的算法示例

选择操作

  • 简单的全表扫描算法

    假设可以使用的内存为M块,全表扫描的算法思想如下:

    • 按照物理次序读Student的M块到内存
    • 检查内存的每一个元组t,如果t满足选择条件,则输出t

    全表扫描只需要很少的内存(最少为一块)就可以运行,而且控制简单。对于规模小的表,这种算法比较有效。对于规模大的表进行顺序扫描,当选择率比较低的时候,这个算法效率很低。

  • 索引扫描算法

  • 选择率:对于一个查询条件,返回结果中符合条件的记录数占总记录数的比例。
  • 检索码:对树中元素进行比较和查找的关键字。

一般情况下,当选择率比较低的时候,基于索引的选择算法要优于全表扫描算法。但是在某些情况下,例如选择率比较高的时候,或者要查找的元组均匀分布在查找的表中,这时基于索引的选择算法性能不如全表扫描。因为除了对表的扫描操作,还要加上B+树索引的扫描操作,对每一个检索码,从B+树根节点到叶子节点路径上的每个节点都要执行一次IO操作。

连接操作

  • 嵌套循环算法。按照数据块存入内存,而不是按照元组进行I/O。

  • 排序-合并算法:

    • 如果参与连接的表没有排好序,首先对Student表和SC表按连接属性Sno排序。
    • 取Student表中第一个Sno,依次扫描SC表中具有相同Sno的元组,把它们连接起来。
    • 当扫描到Sno不相同的第一个SC元组的时候,返回Student表扫描它的下一个元组,重复以上步骤直到完成。

    对于大表,先排序后排序-合并连接算法执行连接,总的时间一般仍会减少。

  • hash join算法:

    • 把连接属性作为hash码,用同一个hash函数把Student表和SC表中的元组散列到hash表中。
    • 第一步:划分阶段,也叫创建阶段,即创建hash表。对包含较少的元组的表(如Student表)进行一遍处理,把它的元组按hash函数分散到hash表的桶中。
    • 第二步:试探阶段:对另一个表(SC表)进行一遍处理,把SC表的元组也按照一个hash函数进行散列,找到适当的hash桶,并把SC元组与桶中来自Student表并与之相匹配的元组连接起来。

连接属性:连接数据库的参数和选项,用于指定数据库连接的相关信息。连接属性包括数据库服务器地址、数据库名称、用户名、密码、端口号、字符集、连接超时时间等。

查询优化

集中式数据库:查询执行开销主要包括磁盘存取块数(I/O代价),处理机时间(CPU代价)以及查询的内存开销。

分布式数据库:IO+CPU+内存+通信代价

一个实例

求选修了2号课程的学生姓名。

数据库系统理论 -- 关系查询处理和查询优化_第1张图片
数据库系统理论 -- 关系查询处理和查询优化_第2张图片

代数优化

代数优化策略是通过对关系代数表达式的等价变价变换来提高查询效率。

具体过程略

物理优化

选择的方法可以是:

  • 基于规则的启发式优化。启发式规则是指那些大多数情况下都适用,单补是在每种情况下都是最好的规则。
  • 基于代价估算的优化。使用优化器估算不同执行策略的代价,并选出具有最小代价的执行计划。
  • 两者结合的方式。

基于启发式规则的存取路径选择优化

选择操作的启发式规则

  • 对于小关系,使用全表顺序扫描,即使选择列上有索引
  • 对于大关系,启发式规则有:
    • 对于选择条件是主码=值的时候,查询结果最多是一个元组,也就是主键索引,说白了就是使用索引覆盖原则。
    • 对于选择条件是非主属性=值的查询,并且选择列上有索引,则要估算查询结果的元组数目,如果比例比较小(< %10),可以使用索引扫描算法,否则还是使用全表顺序扫描。
    • 对于选择条件是属性上的非等值查询或者范围查询,并且选择列上有索引,和上面一条是方案是一模一样的。
    • 对于用AND连接的合取选择条件,查看是否有组合索引,有就优先用组合索引扫描方式。
    • 对于用OR连接的析取选择条件,一般使用全表顺序扫描。

你可能感兴趣的:(数据库,mysql,sql)