mysql索引
1. 索引是什么
索引其实也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
2. 索引的好处:
创建索引可以大大提高系统的性能。
加快mysql的检索速度,这也是建立索引的主要原因;
通过创建唯一性索引,可以保证数据库中每条记录的唯一性;
可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义;
在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间;
通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
3. 索引的坏处:
降低更新表的速度,因为对表进行insert、update、delete时,mysql不仅要保存数据,还要更新索引文件;
建立索引会占用磁盘空间的索引文件,一般情况这个问题不太严重,但如果你在一个大表上创建了多种组合索引,索引文件的会增长很快。
4. 索引的分类:
普通索引: 分为单列索引和组合索引,单列索引,即一个索引只包含一个列,多列索引,即一个索引包含多个列;
唯一索引: 索引列的值必须唯一,但允许有空值,如果是组合索引,则列值的组合必须唯一;
主键索引: 一个表的主键就是一种特殊的唯一索引,不能有空值,一个表只能有一个主键;
组合索引: 指在多个字段上创建的索引,只有在查询条件中使用了创建组合索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀原则。
全文索引: 主要用来查找文本中的关键字,而不是直接与索引中的值相比较。fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配。fulltext索引配合match against操作使用,而不是一般的where语句加like。它可以在create table,alter table ,create index使用,不过目前只有char、varchar,text 列上可以创建全文索引。值得一提的是,在数据量较大时候,先将数据放入一个没有全文索引的表中,然后再用CREATE index创建fulltext索引,要比先为一张表建立fulltext然后再将数据写入的速度快很多。
聚簇索引和非聚簇索引
聚簇索引: 数据行的物理顺序与列值的逻辑顺序相同,一个表中只能拥有一个聚簇索引;
非聚簇索引: 该索引的的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚簇索引。
主键索引属于聚簇索引,普通索引,唯一索引和全文索引都属于非聚簇索引
聚簇索引的查询效率比非聚簇索引的效率要高,但是需要写入性能不高,因为要移动对应数据的物理位置,所以一般建议主键递增的插入方式。
5. 哪些情况不适合加索引
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。
当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
如果每次都需要取表的所有记录;
对于记录比较少的表。
6. 索引的数据结构
InnoDB和MyISAM数据存储引擎中使用B+树来保存索引,但是这两种引擎的实现方式不同。
InnoDB存储引擎支持以下几种索引:
B+ 树索引(B+树就是平衡查找树)
全文索引
哈希索引
InnoDB支持的哈希索引是自适应的,会根据表的使用情况自动为表生成哈希索引,不能人为干预是否在一张表中生成哈希索引。InnoDB存储引擎会监控对表上各索引页的查询,如果观察到哈希索引可以带来速度提升,则建立哈希索引,称之为自适应哈希索引。
B+树索引并不能找到一个给定键值得具体行,B+树索引能找到的只是被查找数据行所在的页,然后数据库通过把页读入内存,再在内存中进行查找,最后得到想要查找的数据。
B+树是为磁盘或其他直接存取辅助设备设计的一种平衡查找树。在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接。
7. B+树和B树的区别
b树(balance tree)和b+树应用在数据库索引,可以认为是m叉的多路平衡查找树,但是从理论上讲,二叉树查找速度和比较次数都是最小的,为什么不用二叉树呢? 因为我们要考虑磁盘IO的影响,它相对于内存来说是很慢的。数据库索引是存储在磁盘上的,当数据量大时,就不能把整个索引全部加载到内存了,只能逐一加载每一个磁盘页(对应索引树的节点)。所以我们要减少IO次数,对于树来说,IO次数就是树的高度,而“矮胖”就是b树的特征之一,它的每个节点最多包含m个孩子,m称为b树的阶,m的大小取决于磁盘页的大小。
B树定义:
描述一颗B树时需要指定它的阶数,阶数表示了一个节点最多有多少个孩子节点,一般用字母m表示阶数。
每个节点最多有m-1个关键字(可以存在键值对)。
根节点最少可以只有1个关键字。
非根节点至少有m/2个关键字。
每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同。
每个节点都存有索引和数据,也就是对应的key和value。
所以,根节点的关键字数量范围:1 <= k <= m-1
,非根节点的关键字数量范围:m/2 <= k <= m-1
。举个例子来说明一下上面的概念,比如这里有一个5阶的B树,根节点数量范围:1 <= k <= 4,非根节点数量范围:2 <= k <= 4。
B+树定义:
前两个是相同点,后4个是不同点:
根节点至少一个元素
非根节点元素范围:m/2 <= k <= m-1
B+树有两种类型的节点:内部结点(也称索引结点)和叶子结点。内部节点就是非叶子节点,内部节点不存储数据,只存储索引,数据都存储在叶子节点。
内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接,便于区间查找和遍历,
父节点存有右孩子的第一个元素的索引。
8. 用不到索引的情况
如果MySQL估计使用索引比全表扫描更慢,则不使用索引。例如,如果列key均匀分布在1和100之间,下面的查询使用索引就不是很好:
select * from table_name where key>1 and key<90;
如果条件中有or,即使其中有条件带索引也不会使用索引(这也是为什么SQL语句中尽量少用or的原因),例如:
select * from table_name where key1='a' or key2='b';
如果在key1上有索引而在key2上没有索引,则该查询也不会走索引;(注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引。)不符合最左前缀的查询不会用到组合索引;
如果like是以‘%'开始的,则该列上的索引不会被使用。例如
select * from table_name where key1 like '%a'
;该查询即使key1上存在索引,也不会被使用;如果列为字符串,则where条件中必须将字符常量值加引号,否则即使该列上存在索引,也不会被使用。例如,
select * from table_name where key1=1;
如果key1列保存的是字符串,即使key1上有索引,也不会被使用;索引列上做运算,也会导致不使用索引。例如,select * from a where b+1 >10;不会使用索引;
参考:
《MySQL技术内幕》
Last updated