MySQL系列(三)---索引
前言:若是有疏忽或理解不当的地方,请指正。有关于数据结构的内容本文没有详细介绍,后续会在数据结构系列进行介绍。html
目录
什么是索引
- 若是没有索引,扫描的记录数大于有索引的记录数
- 索引存放索引列的值(好比id为索引列,那么存放索引列的值),和该索引值对应的行在内存中的地址(或者直接存储该行的数据)
- SELECT * FROM user WHERE username= 'jiajun' ,username创建索引,若是索引采用的数据结构是hash表,那么这个时候,经过计算jiajun的hash值,O(1)复杂度就能够找到该记录的位置
hash索引
- 在等值查找下,此时无hash冲突,这种状况下,效率是很高的
- 可是在范围查找下,因为hash不是有序的,那么范围查找下,hash表的优点并不能发挥出来。
- 在hash冲突下,查找效率会降下来
磁盘读取
- 磁盘读取步骤:定柱面,定磁道,定磁块
- 磁盘时间主要消耗在定位柱面,那么若是要提升速度,在数据量同样的状况下,将尽可能多的数据放在磁盘块上,那么这样能够减小磁头定位柱面移动的次数,减小IO的次数。
二叉查找树
- 左子树全部的节点的值小于他的根节点的值
- 右子树全部的节点的值大于他的根节点的值
- 任意节点的左子树和右子树都是二叉查找树
- 没有键值相等的节点

分析
- 二叉查找树的查找的复杂度到了lgn
- 可是有没有办法减小IO的次数,也就是能不能下降树的高度
B-树
(m阶树 m/2<=k<=m)mysql
- 根节点至少两个子节点
- 全部叶子节点都在同一层
- 中间节点包含k-1个元素和k个孩子
- 节点中的元素从小到大排列
- 每一个节点即包含索引列的值,和该数据记录(或该数据记录的值)

分析
- 相对于二叉查找树,B树变得矮胖,由于每一个节点存放的元素更多,因此相同元素状况下,下降了树的高度,那么就能够减小IO的次数
- 每一个节点存放了数据(该行记录的值或者该行记录在内存的地址),因此不一样的查询性能是不同的。
B+树
- 在B-树的基础上
- 除了叶子结点,其余节点不包含记录(数据库中的行)的位置
- 叶子节点包含了全部的索引值,而且从小到大排列,以及记录(数据库中行)的位置

分析
- 若是节点的大小同样,那么若是咱们除了叶节点以外,其余节点不包含数据,那么就能够放更多的元素(索引值),这样的话这棵树就变的更加矮胖,那么IO的次数能够进一步减小
- 由于叶节点的元素是顺序排列,并且叶节点间造成链表,那么有序查找时提升范围查询的效率
- 相对于B树,因为全部的数据是存放在叶节点,那么意味着每次查找都必须到从根查找到叶节点,那么这就意味着查询性能平均。
总结
- 索引是一种数据,能够避免了全表查询,能够类比目录和书。
- 索引须要一种数据结构来存储
- 利用散列表(hash)的方式查询复杂度能够到O(1),可是再范围查询时,hash起不了提升性能的做用
- IO操做是耗时,为了提升查询性能,能够减小IO的次数
- 对于树的存储结构来讲,为了提升性能,减小IO的次数,能够低树的高度
- 读取一个节点一次IO,在数据量同样的状况下,若是每一个节点的能存放更多元素,那么就能够下降树的高度。
- B树下降了树的高度,而在节点大小同样的状况下,由于B树的节点存放了元素有又存放了数据,而B+树将数据所有存放在叶节点,那么这样的话,每一个节点能够存放更多的元素,那么就能够再一次下降树的高度
- B+树的查询性能更加稳定,而且更有利于范围查找
- 若是是汇集索引(InnoDB引擎),那么节点存放的该记录的数据,数据文件自己就是索引文件
- 若是是非汇集索引(MyISAM引擎),那么节点存放的是该行记录的地址。索引文件和数据文件是分离
索引的种类
- 普通索引,容许出现相同的内容
- 惟一索引,索引值惟一,容许空值
- 主键索引,建立主键的时候自动建立主键索引,惟一而且不能为空
- 组合索引,多列组合索引
汇集索引和非汇集索引
- 汇集索引指的是索引和数据文件在一块儿,在InnoDB引擎中,数据文件自己就是索引文件,这个索引的key是主键。InnoDB必需要主键,若是没有显式指定,则MySQL系统会自动选择一个能够惟一标识数据记录的列做为主键,若是不存在这种列,则MySQL自动为InnoDB表生成一个隐含字段做为主键,这个字段长度为6个字节,类型为长整形。
- 非汇集索引指的是索引文件和数据文件分开。在MyISAM中,B+树中叶节点存放的记录的地址。而在InnoDB中,非主键索引的B+树中存放的是该记录主键值。
索引的使用
- ALTER TABLE table_name ADD INDEX index_name (column_list) 增长普通索引
- ALTER TABLE table_name ADD UNIQUE (column_list) 增长惟一索引
- ALTER TABLE table_name ADD PRIMARY KEY (column_list) 增长主键索引
注意点
- 若是此时为 username,age,sex建联合索引
- 最左匹配指优先匹配最左索引,(username)(username,age)(username,age,sex),只要查询条件用到最左边的列,通常就会使用索引。顺序能够不一样,好比(age,username),这是查询优化器的功劳。
- 模糊查询只有%号不在第一个字符,索引才可能被使用,好比username like '%jiajun'因此不被采用
- 若是or中有一个条件没有索引,sql语句不会用到索引,好比usernmae ='jiajun' or pwd='666',此时索引不被采用
- 组合索引中,若是查询条件不是索引的第一列,索引可能不会被采用,好比此时where age =1
- 若是列是字符型,好比username是字符型并且是索引列,若是此是查询username=1 ,没有加引号,那么这个时候也不会用索引
- 能够用 show status like 'Handler_read%' 来查看索引使用状况。
- 建议实践为主
索引原则
- 索引应该设计在where后的列,而不是select后的列
- 索引应该建在区分度大的列,好比状态只有1 和2就不必建索引了
- 对字符串进行索引的时候,应该制定一个前缀长度,好比一个列为char(200),若是前面几个字符就要较大区分度,那么对前几个字符创建索引就好了,这样减小了占用空间,也提升了速度
- 不要建立太多索引,索引会占空间,并且更新的时候会下降速度,而且若是有过多的索引,Mysql执行计划的时候,会考虑各个索引,这也会浪费时间
哪些列适合索引
- 常常做为查询条件的列
- 常常做为排序条件的列
- 常常做为join条件的列
哪些列不适合索引
- 频繁修改的列,由于数据被修改,索引要相应修改
- 区分度不高的列,好比性别只有两种
- 不是常常做为查询条件,排序条件,链接的列
索引优缺点
- 毫无疑问,在使用正确的状况下,索引能提升查询速度
- 索引也能提升分组和排序的速度
- 因为修改删除添加时,要调维护索引文件,对树进行调整,因此性能下降了
- 索引文件也是须要占用空间的
我以为分享是一种精神,分享是个人乐趣所在,不是说我以为我讲得必定是对的,我讲得可能不少是不对的,可是我但愿我讲的东西是我人生的体验和思考,是给不少人反思,也许给你一秒钟、半秒钟,哪怕说一句话有点道理,引起本身心里的感触,这就是我最大的价值。(这是我喜欢的一句话,也是我写博客的初衷)
做者:jiajun 出处: http://www.cnblogs.com/-new/
本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。若是以为还有帮助的话,能够点一下右下角的【推荐】,但愿可以持续的为你们带来好的技术文章!想跟我一块儿进步么?那就【关注】我吧。sql