mysql-索引


其他笔记链接:
mysql-常用cmd命令
mysql-数据库基础
mysql-索引
mysql-sql优化
mysql-事物

索引

分类

  • 唯一索引
  • 普通索引
  • 全文索引
  • 主键索引
  • 组合索引

作用

1. 用来提高查询效率
2. 可作用于order by,不会进行全排序,索引字段已经排好序

常用概念:回表、索引覆盖、最左匹配、

  1. 回表:当一个普通的索引被使用时,它的叶子节点存储的是本身索引和主键索引,它先查询自己的索引然后从叶子节点获得主键索引,通过主键索引最终得到数据,叫做回表,重用了主键索引。

  2. 索引覆盖:比如name是一个普通索引 ,再查询name索引的时候,因为取的数据时id、name,直接在叶子节点中可以找到,不用再次查找主键的索引,所以叫做索引覆盖,要查询的数据要被索引所覆盖。覆盖索引必须要存储索引列的值,memory存储引擎不支持。

    select name,id from table where name='aa'
    
  3. 最左匹配:组合索引的前提下,name_age_index,从最左开始匹配索引,若筛选条件为age=15则不会走索引,所以叫做最左匹配。

    --不走组合索引
    select * from table where age=15;
    
    --最左匹配
    select * from table where name='15';
    
  4. 索引下推ICP:在Mysql5.7开始,ICP仅用于 二级索引(非聚簇索引)

    区别是一个直接在存储层索引筛选完后继续筛选记录,减少io,不使用icp则会在使用索引后将数据返回server再对这些返回的数据进行筛选,io很大可能会高于第一次的查询

     Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server which evaluates the WHERE condition for the rows. With ICP enabled, and if parts of the WHERE condition can be evaluated by using only columns from the index, the MySQL server pushes this part of the WHERE condition down to the storage engine. The storage engine then evaluates the pushed index condition by using the index entry and only if this is satisfied is the row read from the table. ICP can reduce the number of times the storage engine must access the base table and the number of times the MySQL server must access the storage engine.
     
     如果不使用ICP,则存储引擎将遍历索引以在基表中定位行,并将其返回给server层,然后筛选WHERE条件。 启用ICP后,如果仅可以使用索引中的列来评估WHERE条件的一部分,则MySQL服务器会将WHERE条件的这一部分下推到存储引擎。 然后,存储引擎通过使用索引条目来评估推送的索引条件,并且只有满足此条件的情况下,才从表中读取行。 ICP可以减少存储引擎必须访问基表的次数以及MySQL服务器必须访问存储引擎的次数。
    

b+tree

B+Tree是在BTree的基础之上做的一种优化,变化如下:

1、B+Tree每个节点可以包含更多的节点,这个做的原因有两个,第一个原因是为了降低树的高度,第二个原因是将数据范围变为多个区间,区间越多,数据检索越快

2、非叶子节点存储key,叶子节点存储key和数据

3、叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高

当再插入19 时

聚簇索引、非聚簇索引

  • 聚簇索引:数据和索引存储在一起,tree的叶子节点存储的是数据,innodb存储引擎
  • 非聚簇索引:数据和索引分开存储,tree的叶子节点存储的是数据文件的地址,myisam存储引擎

组合索引

  • 创建索引使用占用空间较小的列
  • 经常范围查找的列放在最后,如果组合索引中一个列使用范围查找后面的索引不会生效
  • 尽量使用索引覆盖,参与的索引列越多在索引生效的情况下效率越高。

Cardinality:基数

该值表示索引中唯一值记录数量的预估值,如索引值有以下取值:1、3、7、3、5、7,则cardinality=4;
在实际应用中,cardinality/rows_num应尽可能接近1,若该值非常小,则需考虑是否要建索引

生效和失效

生效

失效

  • 索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描,在查询语句中不要使用表达式,会严重影响性能
  • 组合索引的最左匹配原则
  • 组合索引的前索引范围查找会使后面的索引失效
  • like 最前面使用%且没使用索引覆盖会导致索引失效。
  • 在索引字段上使用not,<>,!=。不等于操作符是不会用到索引的(not in,<>或者!=会导致索引失效并不是绝对的 对于数据较为均匀的场景是会失效的 但是如果业务数据严重不均的字段加了索引的话是不一定失效的 mysql自己会做判断 并不是绝对判定不使用索引 比如表A性别列有男10000条女20条,当sex!=’男‘是可以使用索引的 同样的如果你sex='男'反而不会使用索引 mysql自己会选择最优的检索方式),因此对它的处理只会产生全表扫描。 优化方法: key<>0 改为 key>0 or key<0。
  • or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效
  • is null 、is not null 也无法使用索引
  • 当全表扫描速度比索引速度快时,mysql会使用全表扫描,此时索引失效,比如索引的基数太小。
  • order by 后使用组合索引需要和前面where条件组成最左匹配,否则也会失效
原文地址:https://www.cnblogs.com/zpyu521/p/12304566.html