mysql索引

为什么使用索引,有什么好处?
1. 可以加快数据的检索速度
 
2. 将随机IO转换成顺序IO(因为列值都是按照从小到大排好序的,数据页或是数据在磁盘中都是相连的,这样的数据很快就能读取出来。称为顺序IO)
 
为什么不对每一个列建索引?页分裂?
1. 从空间角度来说建立一个索引就是建立一个B+树,树中的每一个节点都是一个数据页,一个数据页的大小默认是16KB,树中节点个数很多的话会占用大量的物理空间。
 
2. 从时间的角度上来说每次去修改删除更新数据的操作都会涉及到索引的更新,索引列的值都是按照顺序排列好组成的双向链表(数据页之间是双向链表,而数据之间是单向的链表),在进行这些操作的时候可能会涉及到页面的回收,分裂的操作来维护数据的顺序,如果建立很多索引那么相应的维护步骤会更多,得不偿失了
 
页分裂:在索引中都是按照从小到大的顺序排列的,下一个页面的主键值必须大于上一个页面的主键值,所以需要将数据在页面之间进行移动。比如ID为2的主键记录在页面为5的记录中,ID为1的记录在页面为6的记录中,那么需要将ID为1的记录移动到页面为1中,ID为2的记录移动到页面为2的记录中。
MySql中的索引主要是哪两种数据结构?
1. 哈希索引。 使用的哈希表的实现,在进行单条记录的查询时候哈希索引的执行效率会很高,但是哈希索引不支持范围查询。
 
2. B+树索引。(后面会详细介绍B+树索引,对于B+树索引的实现MyISAM和Innodb是不一样的,后续也会分析Innodb和MyISAM的一些区别)。
 
最左匹配原则的成因?
在对列建立组合索引时,如(name,salary,age)的时候,检索时会用到索引的是(name),(name,salary)和(name,salary,age)这三种。为什么呢?因为组合索引中是先根据最左边的列进行排序,当最左边的列的值相同的时候则看第二个索引去排序,依次往下。所以后面的列都必须依附前面的列。
 
B+树索引的适用条件
1. 全值匹配。如果我们搜索条件的列和索引列是一样的那么就叫做全值匹配。
比如说我们为name,salary建立了一个组合索引(name,salary),那么组合当where句中的条件包含了name和salary时候那么 就使用到了全值匹配。
 
2. 最左匹配。(详情见上面的最左匹配成因)
 
3. 匹配前缀。类似于最左匹配比如字符串进行排序的时候Aabron和Abran进行排序时会先比较第一个字符是否相等如果相等再匹配第二个字符按照从小到大排序。所以使用前缀也是可以用到索引的如:
select * from user where name like 'A%';
 
4. 对索引列进行范围查询也能用到索引(组合索引参照最左匹配原则)。
 
5. 使用order by也可以用到索引(组合索引参照最左匹配原则)
 
6. 使用分组可以用到索引(组合索引参照最左匹配原则)
 
回表是什么?随机IO?顺序IO?
当要查询的记录在非聚簇索引中是不存在的时候需要根据在非聚簇索引中的ID值去聚簇索引中去查找,这样的操作称为回表。比如对表中的age值建立了一个索引,执行查询语句select * from user where age > 1 and age < 5的时候,会先从建立的索引中去查找age > 1 and age < 5的记录,但是该索引中保存的只是该列的值和该表的主键ID值,我们需要查询的是*,即所有的信息,所以就需要到聚簇索引中去根据我们得到的ID去查询出我们需要的数据,age是排好序的也就是说age值在1到5之间的数是连续的,所以读取出来很快,因为这是顺序IO,由于age中的值在1到5之间的值查出来的主键ID值有可能是不连续的也就是说比如age = 2 这条记录对应的主键ID为5,而age = 3这条记录可能对应的ID主键是100,这样就是随机IO,顺序IO比随机IO要快的多。根据age列进行查询时实际上用到了两个索引: 聚簇索引和本身建立的二级索引。二级索引采用了顺序IO,而聚簇索引采用了随机IO。 所以回表的记录越多使用的二级索引的效率就越低。
 
覆盖索引是什么?
查询的结果中只包含了索引列的内容,这样的查找称为覆盖索引。比如对age列建立了索引。那么根据查询语句select age from user where age > 1 and age < 5这样查询,那么查询出来的结果值包含了age也就是索引列,这样只需要用到一次二级索引不需要回表操作就可以查询出来。这样称为索引覆盖。
 
使用索引时需要注意什么?
1. 只为用于搜索的列,或者是用于排序,分组的列去建立索引
 
2. 尽量为基数大的列(基数就是某个列中的值不重复的个数,比如age列的值有1,3,3,1,3那么这个列的基数只有2)建立索引,基数小的列建立索引的话并不划算。
 
3. 对建立索引的列设置为NOT NULL,避免使用全表扫描。
 
4. 进来使用覆盖索引进行查询 避免需要回表的操作。(回表详情见上面)
 
5. 删除表中的重复索引
posted @ 2019-07-02 12:58  丁茜萌萌哒  阅读(144)  评论(0编辑  收藏  举报