定义
- 要全面说明如何执行一个查询,要提供关系代数表达式还要对表达式加上注释说明要如何执行每个操作
- 注释可以声明某个具体操作所使用的算法或者将要使用的一个或者多个的特定索引
- 加上了注释的关系代数被称为计算原语
- 执行一个查询的计算原语序列称为查询执行计划或者查询计算计划
- 查询处理的代价可以通过该查询对各种资源的使用情况进行度量, 各种资源包括 磁盘存取,执行查询时cpu使用的事件以及在并行和分布式数据库系统中通信的代价
- 其中磁盘存取是最主要的代价 cpu执行时间的提升比磁盘速度提升要快很多 这种情况下磁盘存取时间决定着整个查询的时间
- 一般情况下 我们仅使用磁盘存取代价来度量查询执行计划的代价
- 我们使用传送磁盘块数和收缩磁盘次数来度量查询计算计划的代价
- 假设一个磁盘子系统传输一个块的数据平均耗时 $ t_T$秒 磁盘块平均访问时间 (磁盘搜索加旋转延迟)为$ t_s$秒 则
一次传输b个块以及执行S次磁盘搜索的操作将消耗$ b t_T + S t_s $秒
选择算法代价估计表(数据库系统概念 308页)
前提: 所有元组都保存在单个文件上的关系运算
知识点: 码属性 作为主码的属性
- A1: 线性搜索:
- 系统扫描每一个文件块,对所有记录都进行比较是否满足选择条件,开始时需要进行一次磁盘搜索访问文件的第一个块(找到起始点),如果文件的块不是按顺序存放的后续就会需要更多的磁盘搜索不过这里忽略这种情况
- A2: 主索引 码值属性等值比较
- 对应具有主索引的码属性进行等值比较 只需要使用主索引找出对应某一条记录即可 (只有一条记录会符合条件)
- A3: 主索引 非码值等值比较
- 当选择条件是记录非码属性A的等值比较时, 我们使用主索引检索到多条记录 与A2不同的是这可能会检索到多条记录
- A4: 辅助索引 等值比较
- 使用的等值条件可以使用辅助索引 若等值条件是码属性则只能检索出一条符合条件的记录 如果不是则可能会检索出多条记录
- 在第一种情况下: 只能检测出一条的记录 和A2相似
- 在第二种情况下: 可能检测出多条记录 每条记录都可能存储在不同的磁盘块上所以除了遍历树需要的IO操作之外还需要每次检索到记录都需要一次IO操作去传输对应的记录 在需要检索大量数据的情况下性能甚至不如线性搜索
上述表格的辅助索引 存储的是指向记录的指针与innodb不同
如果辅助索引存储主键id则需要对代价公式进行一点调整
优化
对于辅助索引做比较操作时 可以对标非码值属性等值比较 以及A6 这种情况下如果检索的数量很多就还不如使用线性搜索好
因此辅佐索引仅应该在选择到的记录很少时使用
复杂的选择实现
- 合取选择
- 析取选择
- 取反 关系代数的结果是 对 $ theta $条件取值为假的元组集合
- A7: 利用一个索引的合取选择
- 首先判断是否存在 某个简单条件里的某个属性上的一条存储路径 (索引结构被称为存储路径 因为提供了定位和存取数据的一条路径)
- 若存在则在算法A2-A6之中选择一个检索满足该简单条件的记录 然后将检索出的记录缓存到内存中 在内存缓存区里再测试检索到的记录有哪些符合其余条件
- 我们选择某个 $ theta_i $以及A1-A6算法之一 他们组合可以使 $ sigma_{theta_i}(R) $的代价达到最低 算法A7的代价就是这个组合的代价
- 因为根据上述组合可以将符合条件的记录拉取到缓冲区 之后的其余条件对比都不存在IO操作了 查询代价只看IO操作所以忽略掉内存里的操作代价
- 简单的说就是看and条件里有没有主索引或者辅助索引可以用来最小代价得获取到数据 如果有就按选择的索引算法来
- A8: 使用组合索引的合取选择: (需要是等值条件 比较值不行)
- 合取选择可能可以使用合适的组合索引 如果选择指定的是多个属性上的等值条件 并且在这些属性字段组合上又存在组合索引 则可以直接搜索索引 索引的类型将决定使用A2 A3 A4 算法中的哪一个 最差也是辅助索引但是存储位置不连续的代价
- A9: 通过游标的交实现合取选择
- 利用游标(记录指针) 该算法要求各个条件所涉及的字段上有带 游标 的索引
- 该算法对每个索引进行扫描 获取那些 指向 满足单个条件的 记录的游标 所有检测到的游标的交集就是那些满足合取条件的指针的集合
- 该算法利用游标集合获取实际记录 如果并非各个条件上都存在索引 则该算法要用没有索引的条件对检测到的记录进行测试
- A9算法的代价是 扫描各个单独索引代价的总和加上获取检索到的游标列表的交集的实际记录的IO操作
- 对游标列表进行排序并按顺序进行检索记录可以减少代价 (这里涉及到一个排序算法的实现)
- 因此应将指向同一个数据块的游标归在一起 这样就可以一次读取到这个数据块里符合条件的记录
- 以及磁盘块的读取也要按存储位置次序来 这样可以减少磁盘臂的操作
- A10: 通过游标的并实现析取选择
- 如果选择条件上均有索引 则诸葛扫描索引获取满足单个条件的元组游标 检索到的所有游标集合就是析取选择的结构 之后进行IO读取即可(也要进行排序)
- 如果某个选择条件上不存在索引 我们就需要对这个关系进行一次线性查找以找出所有满足条件的元组 因此只要有一个条件没有索引最有效的方法就是线性扫描 扫描的同时对每个元组进行 析取条件的测试
- 均有索引时 代价为 所有索引查找的代价总和 以及 一次集合IO取出
- 某个条件没有索引时 代价为 一次线性查找以及一次集合IO取出