0%

《MySQL是怎样运行的》(三)

索引

概述

  • 常用的数据结构 - B+树

    1. 高度平衡:所有叶子节点处于同一层
    2. 叶子节点存储索引列和主键值(或索引列和完整数据记录),由双向链表构成
    3. 除了叶子节点外,每个节点可以有多个子节点
  • 常见的索引类型

    • 按叶子节点存放的数据分类:聚簇索引(叶子节点存放完整的数据记录,通常主键作为排序条件)和二级索引(需要回表查询完整的数据记录,通常非主键列作为排序条件)
    • 覆盖索引:需要查询的内容包含在索引列中
    • 联合索引:也称复合索引、组合索引,该类型的索引包含了多个数据列,本质也是一个二级索引
  • MyISAM引擎的细节和上述(InnoDB引擎)不完全一样。其将索引和数据分开存储。

    所有数据都存放在数据文件中,索引树存放对应的行号,根据行号查找对应的数据记录

索引的构建及使用

  • InnoDB默认为主键构建一个聚簇索引,叶子节点包含完整的数据记录
  • 用户可以为非主键构建二级索引,该B+树的非叶子节点存放索引列的值、主键值以及对应下一层索引页的页号,叶子节点存放索引列的值和主键值,需要根据主键值再去聚簇索引查找完整的数据记录,因此被称为二级索引
  • 索引在逻辑层面上是B+树,在物理层面上是以页的形式存放,每一页都是同一层的节点,且页与页之间有双向指针相连。页内按照索引列的值大小排成单向链表。
  • 索引页的布局与数据页类似,每一页都分成七个部分,其中数据部分分成若干组,每组中主键大的记录的偏移量会被存储在页目录中的槽中。
  • 进行检索时,每条索引指向与其值相等的第一条记录所在的位置。

索引的优缺点

优点

  1. 提高查找效率
  2. 如果查找的结果需要按照索引条件分组或者排列,也能减少时间开支

缺点

  1. 维护索引需要额外的时间,比如插入数据导致的页面分裂,删除数据导致的索引重新排列等。
  2. 使用索引也需要时间。每次执行查询语句之前,都需要计算不同的索引所需的时间成本,生成一个执行计划。如果索引过多,就有可能导致这个生成执行计划的时间过长。
  3. 建立索引需要占用额外的空间。每创建一个索引就是构建一个新的二叉树,二叉树的节点需要占据空间。

如何创建合适的索引

  • 为常用作搜索条件的列创建索引 为常出现在WHERE、ORDER BY、GROUP BY子句中的列创建索引,仅出现在查询列表中的列就不必要创建索引
  • 不为含有太多重复值的列创建索引 如果某列中重复的数值很多,该列就不适合作为快速搜索的条件,因此不必要创建索引
  • 索引列的数据类型占用空间尽可能小 为某列创建索引,索引树的节点中就都存放有该列的值,如果值的类型占用的存储空间太大,就会产生不必要的空间消耗。例如使用INT类型就足够表示,就不必要使用BIGINT类型。
  • 为列前缀创建索引 可以将字符串中的前几个字符存放到索引中。
  • 创建覆盖索引 常出现在查询列表中的列可以创建覆盖索引,这样B+树中的叶子节点就有需要的结果,不需要回表查询,减少时间开销。
  • 不要在搜索条件中进行索引列的运算 例如以key列创建了索引,如果WHERE子句中的搜索条件是WHERE key * 2 < 4,那么MySQL将使用全表扫描而不使用索引。
  • 表的主键设置为自动递增 MySQL默认为表格的主键列创建聚簇索引,如果主键不是递增的,那么插入新记录时就有可能导致正好插入到已满的数据页的中间,此时MySQL需要进行页面分裂,并把一些数据移动到新的页面中,造成无谓的性能损耗。
  • 不要创建冗余和重复索引 例如本身已经创建了一个针对key1\key2的联合索引,就不需要单独再为key1创建索引了