MySql索引总结

MySQL 索引底层数据结构

  Mysql索引使用的数据结构主要有 BTree索引Hash索引。对于Hash索引来讲,底层数据结构就是哈希表,所以在绝大多数需求为单条记录查询的时候,使用Hash索引查询性能最快。其他大多数场景建议使用BTree索引。html

为何索引可以提升查询速度

  MySQL的基本存储结构为 ,页与页之间使用双向链表进行连接,页内记录使用单向链表进行连接。查询数据时,先使用双向链表查询到数据所在的页,页内查询时,where子句中若是是主键则根据二分查找进行查询,若是为非主键则使用遍历链表的方式进行查询。整个时间复杂度为O(n)。面试

  使用索引以后,能够利用BTree的数据结构进行查找数据,时间复杂度能够作到O(log n)。sql

使用索引的缺点

  • 建立索引和维护索引须要耗费时间,这种时间随着数据量的增长而增长。
  • 索引须要占用物理空间,数据量越大,占用的空间越大。
  • 在进行增删改的过程当中,因为须要维护索引,所以会下降效率,对于增删改操做比较多的表,不适合创建太多索引。

MySQL索引类型

  1. 主键索引:特殊的索引,惟一的标识一条记录,不能为空,通常用primary key来约束。
    ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 
    复制代码
  2. 惟一索引:索引列的值必须惟一,且不能为空,若是是组合索引,则列值的组合必须惟一。
    ALTER TABLE `table_name` ADD UNIQUE ( `column` ) 
    复制代码
  3. 普通索引:最基本的索引,它没有任何限制。
    ALTER TABLE `table_name` ADD INDEX index_name ( `column` )
    复制代码
  4. 全文索引:全文索引(FULLTEXT)仅能够适用于MyISAM引擎的数据表;做用于CHAR、VARCHAR、TEXT数据类型的列。
    ALTER TABLE `table_name` ADD FULLTEXT ( `column`) 
    复制代码
  5. 联合索引:将几个列做为一条索引进行检索,使用最左匹配原则。
    ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )
    复制代码

联合索引的最左匹配原则

简单来说,创建联合索引时,当最左边的一个或多个索引肯定以后,紧跟着的索引才是有序的。(以下图,创建a,b的联合索引后,a的值为[1,1,2,2,3,3]有序,b的值为[1,2,1,4,1,2])当不肯定a的值时,b的值在结构上是无序的,这时仅where子查询中若是只使用b进行查找则会全表查找。 因此当咱们用 where a = 1 and b = 2 进行查询时,因为a肯定以后b的值有序,因此b字段查询时使用上索引。当咱们用 where a > 1 and b = 2 进行查询时,a字段可使用索引,但b字段因为无序因此没法使用索引。数据库

join index

  • 总结
  • 最左前缀匹配原则。MySQL会一直向右匹配直到遇到范围查询(>,<,BETWEEN,LIKE)就中止匹配,好比: a = 1 AND b = 2 AND c > 3 AND d = 4,若是创建 (a,b,c,d)顺序的索引,d是用不到索引的,若是创建(a,b,d,c)的索引,则均可以用到,a,b,d的顺序能够任意调整。
  • 等于(=)和in 能够乱序。好比,a = 1 AND b = 2 AND c = 3 创建(a,b,c)索引能够任意顺序,MySQL的查询优化器会帮你优化成索引能够识别的模式

汇集索引和非汇集索引

简单归纳markdown

  • 汇集索引就是以主键建立的索引
  • 非汇集索引就是以非主键建立的索引

两者区别数据结构

  • 汇集索引中,叶子节点存储的是表中的数据
  • 非汇集索引中,叶子节点存储的是主键和索引列
  • 使用非汇集索引查询出数据时,拿到叶子上的主键再去查到想要查找的数据。(拿到主键再查找这个过程叫作回表)
  • 建立多个非汇集索引,每一个汇集索引会生成一个索引树,所以创建多个索引会占用更多的磁盘空间。

索引和查询优化的注意事项

  • 前导的模糊查询没法使用索引,如 where like '%索引' 没法使用索引
  • Union、in、or能够命中索引,建议使用in
  • 负条件查询不能使用索引,能够优化为in查询,其中负条件有!=、<>、not in、not exists、not like等
  • 创建联合查询时,区分度最高的字段在最左边
  • 把计算放到业务层而不是数据库层,由于在字段上计算不能命中索引
  • 强制类型转换会全表扫描,若是phone字段是varcher类型,则下面的SQL不能命中索引。Select * fromuser where phone=13800001234
  • 创建索引的列不能为null,使用not null约束及默认值(这里多谢掘友指出,表述有点不恰当,创建索引的列若是为null,将会使索引失效,因此说“创建索引的列不能为null”)
  • 若是明确知道查询结果只要一条,limit 1可以提升效率,好比验证登陆的时候
  • 使用合理的分页提升效率。select id,name from product limit 866613, 20使用上述SQL语句作分页的时候,可能有人会发现,随着表数据量的增长,直接使用limit分页查询会愈来愈慢。优化的方法以下:能够取前一页的最大行数的id,而后根据这个最大的id来限制下一页的起点。好比此列中,上一页最大的id是866612。SQL能够采用以下的写法:select id,name from product where id> 866612 limit 20。

面试经历

Q:请说说索引的注意事项,或者说说索引的优缺点。oop

参考资料:

相关文章
相关标签/搜索