【MySQL进阶】索引

目录

索引基本概念

什么是索引

MySQL中两种数据访问方式

顺序访问

索引访问

什么时候需要创建索引

1.经常用于查询条件的列

2. 经常用于排序的列

3. 经常用于连接操作的列

4. 唯一性约束的列

5. 经常用于分组的列

6. 覆盖索引

索引的数据结构

二叉树

平衡二叉树

Hash

B-Tree

B+-Tree

InnoDB和MyISAM

MyISAM索引

InnoDB索引

对比

InnoDB

MyISAM


索引基本概念

什么是索引

索引是数据库管理系统(DBMS)中一种用于快速查找数据的方法。它是数据库表中一列或多列的有序数据结构,通过对这些列进行排序并生成索引,数据库可以更快地执行查询操作。

MySQL中两种数据访问方式

顺序访问

顺序访问是从表的第一条记录开始访问,直到访问到最后一条。

  • 性能:当表中数据量较大时,顺序访问的性能较差,因为需要逐行读取所有记录。
  • 适用场景:通常在没有索引或者索引不可用的情况下使用,比如对于小表或返回大量数据的查询

索引访问

索引访问就是我们在查询数据是在索引数据结构上执行的(如B树,哈希表等),索引数据首先是排好序的,其次它没有保存完整的数据列(聚簇索引除外,它的数据记录在叶子节点上的)。如果创建了索引之后,当我们对数据进行更新操作时,需要同时更新和维护索引资源。

  • 性能:索引访问通常比顺序访问更快,尤其是当表中数据量很大时。索引能够显著减少需要读取的记录数量。
  • 适用场景:适用于查询条件中包含索引列的场景,可以大幅提高查询效率。

什么时候需要创建索引

1.经常用于查询条件的列

如果某列经常出现在 WHERE 子句中,可以考虑为该列创建索引。例如:

如果查询条件中频繁使用 age 列,那么可以为 age 列创建索引:

SELECT * FROM employees WHERE age > 30;

CREATE INDEX idx_age ON employees(age);

2. 经常用于排序的列

如果某列经常出现在 ORDER BY 子句中,可以考虑为该列创建索引。例如:

如果排序操作频繁使用 name 列,那么可以为 name 列创建索引:

SELECT * FROM employees ORDER BY name;

CREATE INDEX idx_name ON employees(name);

3. 经常用于连接操作的列

如果某列经常出现在表连接的 JOIN 子句中,可以考虑为该列创建索引。例如:

如果连接操作频繁使用 dept_id 列,那么可以为 dept_id 列创建索引:

SELECT * FROM employees e JOIN departments d ON e.dept_id = d.id;

CREATE INDEX idx_dept_id ON employees(dept_id);

4. 唯一性约束的列

对于具有唯一性约束的列,创建唯一索引可以确保数据的唯一性。例如:

CREATE UNIQUE INDEX idx_unique_email ON employees(email);

5. 经常用于分组的列

如果某列经常出现在 GROUP BY 子句中,可以考虑为该列创建索引。例如:

如果分组操作频繁使用 dept_id 列,那么可以为 dept_id 列创建索引:

SELECT dept_id, COUNT(*) FROM employees GROUP BY dept_id;

CREATE INDEX idx_group_dept_id ON employees(dept_id);

6. 覆盖索引

当索引包含所有查询所需的列时,查询可以直接从索引中获取数据,而无需访问表。例如:

如果为 dept_idnameage 列创建复合索引:

SELECT name, age FROM employees WHERE dept_id = 1;

CREATE INDEX idx_covering ON employees(dept_id, name, age);

注意事项

  1. 不必要的索引:不要为每一列都创建索引,索引过多会增加插入、删除和更新操作的开销,并占用更多的存储空间。
  2. 选择性:选择性高的列(即具有大量不同值的列)适合创建索引,选择性低的列(如性别)不适合单独创建索引。
  3. 复合索引:对于多列查询,可以考虑创建复合索引(多列索引),但要注意列的顺序和查询的使用情况。
  4. 维护成本:索引需要维护,因此在频繁进行写操作(插入、删除、更新)的表上,需要慎重考虑是否创建索引。

总结

创建索引可以大幅提高查询性能,但需要根据具体应用场景和查询模式来合理创建索引。避免不必要的索引,选择性高的列和常用的查询条件、排序、连接、分组列是创建索引的主要考虑因素。

索引的数据结构

二叉树

二叉树是一种树形数据结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。

二叉树的特点:每个节点最多有2个分叉,左子树和右子树数据顺序左小右大。

二叉树的实现主要为了每次查找都可以折半而减少IO次数,但还有种极端情况下很容易出现树不分叉,这时候查询时间复杂度为O(n)如下图:

平衡二叉树

平衡二叉树除了具备二叉树的特点之外,最主要的特征是它的左右两个子树的高度差的绝对值不超过1。这个方案很好的解决了二叉查找树退化成链表的问题,在插入删除数据时通过左旋/右旋操作保持二叉树的平衡,不会出现左子树很高、右子树很矮的情况。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间。

可以看到当我们顺序插入1,2,3,4,5时候,平衡二叉树会通过旋转的方式使得数据分布较为均匀。

存在问题:

  • 实现复杂

    • 平衡二叉树的实现比普通二叉搜索树要复杂得多。需要额外的逻辑来维护树的平衡,特别是插入和删除操作后,需要执行旋转操作来恢复平衡。
  • 插入和删除操作的开销

    • 虽然插入和删除操作的时间复杂度在最坏情况下仍然是O(log n),但平衡二叉树在这些操作过程中需要进行额外的旋转和调整,导致常数因子较大,实际开销较高。

Hash

哈希表通常由以下两个主要部分组成:

  1. 数组

    • 一个固定大小的数组,用于存储数据项或指向数据项的指针。
  2. 哈希函数

    • 一个用于将键映射到数组索引的函数。理想的哈希函数应尽可能均匀地分布键,以减少冲突。
  3. 冲突处理机制

    • 当两个不同的键映射到同一个索引时,称为冲突。常见的冲突处理方法包括链地址法(链表法)和开放地址法(如线性探测、二次探测和双重哈希)。

优点

  1. 快速查找

    • 在平均情况下,哈希表可以在O(1)时间复杂度内完成查找操作。
  2. 快速插入和删除

    • 插入和删除操作的平均时间复杂度也是O(1),这使得哈希表在需要频繁插入和删除操作的应用中非常高效。
  3. 实现简单

    • 基本的哈希表实现相对简单,适用于需要快速存取的数据集合。

缺点

  1. 哈希冲突

    • 哈希冲突是无法完全避免的,处理冲突需要额外的开销。选择合适的哈希函数和冲突处理机制是关键。
  2. 内存浪费

    • 为了减少冲突,哈希表通常需要分配比实际存储数据更多的内存空间,这可能导致内存浪费。

B-Tree

MySQL的数据是存储在磁盘文件中的,查询数据时需要先把磁盘中的数据加载到内存中,磁盘IO操作非常耗时,所以我们优化的重点就是尽量减少磁盘IO操作,所以,我们应当尽量减少从磁盘中读取数据的次数。另外,从磁盘中读取数据时,都是按照磁盘块来读取的,并不是一条一条的读。如果我们能把尽量多的数据放进磁盘块中,那一次磁盘读取操作就会读取更多数据,那我们查找数据的时间也会大幅度降低。当数据极大的时候,二叉树的节点也是海量的,高度也会及其高,我们查找数据时也会进行很多次磁盘IO,我们查找数据的效率将会极低!为了解决这个问题,B树应运而生,B树是一种多叉平衡查找树。

B树的特点

  1. 自平衡

    • B树始终保持平衡,所有叶子节点都在同一层上。因此,从根节点到任何叶子节点的路径长度相同,这保证了查找、插入和删除操作的时间复杂度为O(log n)。
  2. 多叉性

    • B树的每个节点可以有多个子节点,而不仅仅是两个(如在二叉树中)。具体来说,B树的每个节点最多可以有m-1个键和m个子节点,其中m是B树的阶数(degree)。
  3. 节点包含多个元素

    • 每个节点包含多个元素(键)和子节点指针,而不仅仅是单个值。节点中的元素按顺序存储,以便进行高效的范围查询。

B+-Tree

特点

  • 非叶子节点不存储data,只存储索引,可以放更多的索引
  • 叶子节点包含所有索引字段
  • 叶子节点用双向指针连接,提高区间访问的性能

InnoDB和MyISAM

MyISAM索引

MyISAM的数据文件和索引文件是分开存储的。MyISAM使用B+树创建索引树时,叶子节点中存储的键值为索引列的值,数据为索引所在行的磁盘地址。所以MyISAM只支持非聚簇索引。

InnoDB索引


InnoDB是默认的MySQL存储引擎,虽然InnoDB也使用B+树作为索引结构,但具体实现方式却与MyISAM截然不同。InnoDB的数据文件本身就是索引文件,而从上文中我们知道,MyISAM索引文件和数据文件是分离的,索引文件仅保存数据记录的地址,而在InnoDB中,表数据文件本身就是按B+树组织的一个索引结构,这棵树的叶子节点data保存了完整的数据记录。这个索引的key是表的主键,因此InnoDB表数据文件本身就是主索引。支持聚簇索引。

对比

InnoDB

  1. 数据结构

    • InnoDB使用B+树作为索引数据结构,支持聚簇索引(clustered index)。数据文件本身就是主索引(主键),次索引则存储主键值。
  2. 事务支持

    • InnoDB支持ACID(Atomicity, Consistency, Isolation, Durability)事务,并实现了事务的4种隔离级别(读未提交、读提交、可重复读、串行化)。
  3. 行级锁定

    • InnoDB支持行级锁定,这意味着在并发写操作时,锁定的是行而不是表,从而提高了并发性能。
  4. 外键支持

    • InnoDB支持外键约束,可以维护数据的完整性和一致性。
  5. 崩溃恢复

    • InnoDB有崩溃恢复功能,通过使用重做日志(redo log)和回滚日志(undo log)来保证数据的一致性和持久性。
  6. 性能

    • InnoDB在写操作频繁的应用场景中表现更好,适用于高并发的事务处理系统。
  7. 适用场景

    • 需要事务支持和数据完整性的应用,如银行系统、电商平台等。

MyISAM

  1. 数据结构

    • MyISAM也使用B+树作为索引数据结构,但不支持聚簇索引。数据和索引是分开的,索引叶子节点存储的是数据记录的地址。
  2. 事务支持

    • MyISAM不支持事务处理,因此不支持ACID属性。
  3. 表级锁定

    • MyISAM只支持表级锁定,在并发写操作时会锁定整个表,从而降低了并发性能。
  4. 外键支持

    • MyISAM不支持外键约束,因此不能自动维护数据的完整性。
  5. 崩溃恢复

    • MyISAM没有内置的崩溃恢复机制,数据在系统崩溃后可能需要手动修复。
  6. 性能

    • MyISAM在读操作频繁的应用场景中表现更好,适用于读多写少的应用。
  7. 适用场景

    • 适用于数据分析和查询频繁的应用,如数据仓库、日志分析系统等。
特性InnoDBMyISAM
数据结构B+树(支持聚簇索引)B+树(不支持聚簇索引)
事务支持支持不支持
锁定机制行级锁定表级锁定
外键支持支持不支持
崩溃恢复支持不支持
性能写操作和高并发性能较好读操作性能较好
适用场景需要事务和数据完整性支持的应用,如银行、电商读操作频繁的应用,如数据仓库、日志分析

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值