索引

索引是表的目录,是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,以此快速定位查询数据。对于索引,会保存在额外的文件中。

Mysql数据库使用B+树来实现索引的。B+树的特点就是叶子节点包含了所有的关键字信息和data数据,非叶子节点只包含子节点的最大或者最小关键字,用来实现索引。
好处:既能实现快速查找,相比于B树又节约了内存空间。

(注:底层的索引实现存储方式由:顺序文件上的索引、B+树的索引、散列索引、位图索引等

Mysql数据库中的索引实现主要依赖于两个存储引擎,MyISAM和InnoDB,都是使用B+树作为索引结构。区别就是MyISAM中使用B+树的叶子节点的data域存放数据的内存地址,而InnoDB中树的叶节点data域保存了完整的数据。

优缺点

索引可以提高查询速度,会减慢写入速度,索引的缺点是创建和维护索引需要耗费时间。也占物理空间,对数据库进行增删改的时候也要动态的维护索引。
索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引。

什么样的字段适合创建索引
  1. 表的主键、外键必须有索引;外键是唯一的,而且经常会用来查询
  2. 经常与其他表进行连接的表,在连接字段上应该建立索引;
  3. 数据量超过300的表应该有索引;
  4. 重要的SQL或调用频率高的SQL,比如经常出现在where子句中的字段,order by,group by, distinct的字段都要添加索引
  5. 经常用到排序的列上,因为索引已经排序。
  6. 经常用在范围内搜索的列上创建索引,因为索引已经排序了,其指定的范围是连续的
什么场景不适合创建索引
  1. 对于那些在查询中很少使用或者参考的列不应该创建索引,这是因 为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
  2. 对于那 些只有很少数据值的列也不应该增加索引。因为本来结果集合就是相当于全表查询了,所以没有必要。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比 例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  3. 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
  4. 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因 此,当修改性能远远大于检索性能时,不应该创建索引。
  5. 不会出现在where条件中的字段不该建立索引。
  6. 如果列均匀分布在 1 和 100 之间,却只是查询中where key_part1 > 1 and key_part1 < 90不应该增加索引
    Mysql索引使用的数据结构主要有BTree索引 和 哈希索引 。对于哈希索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择哈希索引,查询性能最快;其余大部分场景,建议选择BTree索引。
索引分类
  1. 聚集索引
  2. 非聚集索引(辅助索引或者二级索引)

聚集索引:

  1. 主键索引(PRIMAY KEY):加速查找,约束列数据不能重复,数据不能为 null;聚集索引可以理解为主键,一个表只能有一个聚集索引

非聚集索引:

  1. 唯一索引(UNIQUE) :与普通索引类型,不同的是:加速查询 + 列值唯一(可以有null)
  2. 常规索引(INDEX):仅加速查询 最基本的索引,没有任何限制,是我们大多数情况下使用到的索引。
  3. 全文索引(FULLTEXT):全文索引(fulltext)仅可以适用于MyISAM引擎的数据表;作用于CHAR、VARCHAR、TEXT数据类型的列。


不同引擎下的索引内部结构

Mysql的BTree索引使用的是B数中的B+Tree,但对于主要的两种存储引擎的实现方式是不同的。

MyISAM: B+Tree叶节点的data域存放的是数据记录的地址。在索引检索的时候,首先按照B+Tree搜索算法搜索索引,如果指定的Key存在,则取出其data域的值,然后以data域的值为地址读取相应的数据记录。这被称为“非聚簇索引”。

InnoDB: 其数据文件本身就是索引文件。相比MyISAM,索引文件和数据文件是分离的,其表数据文件本身就是按B+Tree组织的一个索引结构,树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引。这被称为“聚簇索引(或聚集索引)”。而其余的索引都作为辅助索引,辅助索引的data域存储相应记录主键的值而不是地址,这也是和MyISAM不同的地方。在根据主索引搜索时,直接找到key所在的节点即可取出数据;在根据辅助索引查找时,则需要先取出主键的值,在走一遍主索引。 因此,在设计表的时候,不建议使用过长的字段作为主键,也不建议使用非单调的字段作为主键,这样会造成主索引频繁分裂。

聚集索引与非聚集索引的区别

认清一点,聚簇索引以及非聚簇索引并不是一种单独的索引类型,而是一种数据存储方式。
《高性能MySQL》读后感——聚簇索引

  1. 聚集索引可以查到需要查找的数据
  2. 通过非聚集索引可以查到记录对应的主键值 , 再使用主键的值通过聚集索引查找到需要的数据
  3. 不管以任何方式查询表, 最终都会利用主键通过聚集索引来定位到数据, 聚集索引(主键)是通往真实数据所在的唯一路径

myisam的索引和数据分开存储 mysql索引是在内存中吗_数据

结论:
  1. 索引的数据结构:非二叉平衡树(B树、B+树)
  2. 表要加主键(聚集索引)
  3. 加索引后会使查询变快
    先通过属性索引找到需要的主键值,再通过聚集索引找到需要的数据,不需要扫描所有数据
  4. 加索引后会使写入、修改、删除变慢
    平衡树这个结构必须一直维持在一个正确的状态, 增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构, 因此,在每次数据改变时, DBMS必须去重新梳理树(索引)的结构以确保它的正确
  5. 有时需在多个字段上建索引,可以大大提高查询效率