索引是一种数据结构,用来提高查询效率。
(那么多的数据,当然要想办法提高查询效率啦啊)
常见的索引有Hash 索引 和 B+树索引。
Hash索引和B+树索引的区别?
Hash索引适合做等值查询;hash会出现hash碰撞,如果hash碰撞严重,查询效率就会降低。 (Nosql中就是用的 k-v,也就是用的hash了)
B+树可以进行范围查询,联合查询的最左匹配原则,
B+树和B树的区别?
B树是一种多路平衡树。
子树的个数等于结点中的元素的个数+1;
查询可以在非叶子结点命中;
一个M阶的B树,根节点至少有两个元素,非根节点的元素个数为 [ M/2, M ]
B+树在B的基础上进行了改进:
子树的个数等于结点的元素的个数;
查询都是在叶子结点命中;
叶子结点有指向两边的指针,用于范围查询。
B*树在B+树的基础上进行了改进:
非根结点的元素的个数至少为2/3M,
非叶子结点也加入了指向两边的指针
为什么不用二叉搜索树?
二叉搜索树的效率近似于二分查找,效率高于B+树,但是考虑到IO操作的时间,果断选取B+树。(树越扁平越好)
为什么建立了索引却没有走索引?
索引失效?
聚簇索引 非聚簇索引
聚簇索引: 指的是叶子结点中存储的数据 ( innodb采用的就是聚簇索引,因此它的存储文件就只有两个)
非聚簇索引: 指的是叶子结点中存储的数据的地址 (MyIsam采用的是非聚簇索引,因此它的存储文件有三个)
聚簇索引也叫 主键索引、一级索引,那么相对应的就有非主键索引、二级索引、普通索引,它的叶子结点存储的就是主键索引的值,还要进行一次回表查询,可以通过建立覆盖来不进行回表。
主键索引和普通索引的区别?
普通索引还需要进行回表。
那怎么可以不进行回表?
通过覆盖索引!!覆盖索引,是通过联合索引来实现的!
联合索引
联合索引就是多个字段建立索引,联合索引要符合最左前缀匹配原则,注意!!这地方有的时候查询可能不走索引,就是因为不符合最左前缀匹配原则。
比如:我们通过 (name,age,adress)建立了联合索引。
比如 select * from T where age=19 and address='sd' 联合索引失效,不符合最左前缀匹配原则
select * from T where name like '%fa' 联合索引失效,不符合最左前缀匹配原则
索引下推:
在联合索引中就进行判断是都满足条件,不满足添加的不进行回表,如果不进行索引下推,
比如 selct * from T where name like '张%' and age=9; 符合最左前缀原则,但是如果不支持索引下推,就会忽视掉age这个字段,找到所有符合添加的name, 然后回表,查出完整记录后,再进行age的比较。如果支持索引下推,就会先比较age的值,不满足的就直接不进行回表了!
为什么要有自增主键?
这就涉及到了索引的维护,数据的添加和删除,会破坏索引的结构,调整索引需要消耗时间,采用自增主键,就可以之间往后添加元素就可以了,不需要做大的索引结构的变动。
普通索引和唯一索引:
唯一索引就是索引的字段值不会重复。那么在查询的时候,通过唯一查询可以查询到一条记录,通过普通查询,还需要继续向后查询,找到第一个不满足查找的索引结束。 这个差别并不大。
两者真正的差别在插入数据上面。这里用到了 Change Buffer
如果要操作的页在内存中,那直接操作内存即可。如果不在内存中,那就可以使用Change Buffer, 只有普通索引才可以用change buffer,因为唯一索引还要判断索引是否冲突!!而且如果,插入后,马上进行查询,还是会要进行磁盘IO,然后将Chage buffer的内容写到页中,然后再进行查询(显然,这不但没提高效率,还降低了效率)。如果没有进行查询,则再适合的时间进行change buffer写到磁盘中。所以 change buffer适合用在写多读少的地方。注意:这个根redolog并不冲突,在change buffer中的修改,也会写到 redolog中,进行持久化。
change buffre 减少了随机读磁盘的io消耗(本应该将数据从磁盘中读进内存进行更新,但是为了提高速度,先不读取到内存中了,直接在内存中的change buffer区域进行更新操作),redo log节省了随机写磁盘的io消耗(改为按顺序写)(redolog是在更新数据库的时候用到的,这时候在内存中已经修改了数据了,但是还没有写回磁盘)
(所以,意思就是尽量使用普通索引)
Mysql在执行时索引是怎么选取的?
Mysql在执行sql语句时,用哪个索引是由mysql的优化器决定的!!通过 explain可以看到它实际走的索引
(优化器 通过判断 扫描行数、是否使用临时表、是否排序等进行综合判断,来选取使用哪个索引)
怎么给字符串字段加索引?
比如给邮箱地址加上索引。可以采用取字符串给的前面几位作为索引!!
(心中要记住一点,建立索引关注的是区分度!! 要看一下前几位的区分度就比较好了,将让前面这些位做索引!)
但是使用了前缀索引,就没法用覆盖索引了!!因此这时,必须要回表进行比较字符串的完整值是否匹配.
对于身份证这样的建立索引,可以采用反转,然后取前几位的方式;或者加一个字段,存储它的hash值,用hash来作为索引。
也许会有遗憾,但是不应该在失败之前