数据库调优

image.png

范式与反范式

相关概念

  • 超键: 能唯一表示元祖的属性集叫做超键
  • 候选键: 如果超键不包括多余的属性, 那么这个超键就是候选键
  • 主键: 用户可以从候选键中选择一个作为主键
  • 外键: 如果数据表R1中的某属性集不是R1的主键, 二是另一个数据表R2的主键, 那么这个属性集就是数据表R1的外键
  • 主属性: 包含在任意候选键中的属性称为主属性
  • 非主属性: 与主属性相对, 只的是不包含任何一个候选键中的属性

  • 1NF: 数据库表中的任何属性都是原子性的, 不可再分. 事实上, 任何的DBMS都满足第一范式.

  • 2NF: 数据表里的非主属性完全依赖于候选键.
  • 3NF: 任何非主属性直接依赖于候选键.
  • 反范式: 允许少量冗余, 空间换时间

示例:
image.png
仓库和管理员是严格绑定的一对一关系, 同时仓库+物品能决定数量这个属性, 管理员+物品也能决定数量, 因此

  1. 候选键是(管理员, 物品名)和(仓库名, 物品名), 可选一个主键, 比如(仓库名, 物品名)
  2. 主属性是仓库名, 物品名, 管理员, 非主属性是数量, 由上面分析可知, 数量直接依赖于(管理员, 物品名)或(仓库名, 物品名)的候选键, 因此满足三大范式

但依然有问题, 如:

  1. 新增仓库, 可以不存任何物品, 但要求主键(仓库名, 物品名)不能为空, 会出现异常;
  2. 若仓库换管理员, 则需要修改多条记录;
  3. 若仓库商品卖空, 则仓库以及管理员记录没有了

因此引入BCNF(巴斯-科德范式), 在3NF基础上消除了主属性对候选键的部分依赖或传递依赖关系.
按BCNF要求, 上面示例表需被拆分为: 仓库表(仓库名, 管理员), 库存表(仓库名, 物品名, 数量)

索引

索引种类

  • 普通索引
  • 唯一索引: 在普通索引上添加了唯一性约束
  • 主键索引: 在唯一索引上添加了非空约束
  • 全文索引

索引数据结构

  1. 二叉搜索树
  • 查询时间复杂度为O(logn), 特殊情况退化成链表则为O(n)

image.png

  1. 平衡二叉树, 即AVL树(平衡二叉搜索树, 红黑树, 数堆, 伸展树)
  • 在二分搜索树的基础上增加了约束,每个节点的左子树和右子树的高度差不能超过 1,也就是说节点的左子树和右子树仍然为平衡二叉树
  • 查询时间复杂度为O(logn), 时间复杂度取决于树的深度, 树的深度是O(logn)
  1. M叉树
  • 通过增加分叉来降低深度, 提高查找效率

image.png

  1. B树, 平衡的多路搜索树
  • 每个节点最多可以包括M个子节点, M成为B树的阶
  • 每个磁盘块中包含关键字和子节点的指针

image.png

  1. B+树

与B树相比, 结构上:

  • 子节点个数=关键字树, 而B树子节点数=关键字数+1
  • 非叶子节点仅用于索引, 不保存数据记录, 而B数非叶子节点既保存索引也保存数据记录
  • 所有关键字在叶子节点出现, 并且叶子节点构成一个有序链表

这些结构上的优化, 带来:

  • B+树查询效率更稳定, 因为所有数据都保存在叶子结点, 无需在非叶子节点去查找
  • B+树查询效率更高, 同样的磁盘页大小, B+树可以存储更多的节点关键字, 使得B+树的阶数更大, 分叉越多, 深度更低, 更”矮胖”, 因此查询所需的磁盘I/O更少
  • 在范围查询上, B+树的效率也更高, 因为B+树的叶子节点形成了有序链表结构

image.png

Hash索引与B+树索引的区别

  1. Hash索引指向的数据是无序的, 因此Hash索引不能范围查询, 也不支持ORDER BY排序
  2. Hash索引是对索引键计算Hash值, 因此不支持联合索引的最左匹配原则, 也不支持模糊查询