参考资料:

http://blog.csdn.net/v_july_v/article/details/6530142
http://blog.codinglabs.org/articles/theory-of-mysql-index.html
https://dev.mysql.com/doc/refman/5.6/en/mysql-indexes.html
https://www.zhihu.com/question/36996520
https://stackoverflow.com/questions/21927117/what-is-this-operator-in-mysql
http://thephper.com/?p=142

0. 环境

MySQL: 5.6.22

1. 概述

大部分MySQL索引(PRIMARY KEY, UNIQUE, INDEX, FULLTEXT)是以B+tree算法存储。例外:

  • 基于空间数据类型(spatial data types)使用R-trees算法
  • MEMORY引擎支持Hash算法
  • InnoDB引擎的全文检索索引(FULLTEXT)使用倒排列表(inverted lists)算法

2. B+tree索引与Hash索引的区别

B+tree索引可以在=, >, >=, <, <= 和 BETWEEN操作中使用,也适用于不以通配符开始的LIKE操作(eg. LIKE '1%' or LIKE '1%2%'),而Hash索引限制如下:

  • 仅适用于=, <=> 操作且检索速度很优秀('a' IS NULL等价于'a' <=> NULL,<=>只能用于Mysql)
  • 无法使用Hash索引优化ORDER BY
  • 无法使用Hash索引计算两个值间区间大小
  • Hash索引不能拆分使用(相对于B-tree的最左匹配原则)

3. 为什么使用B+tree?

由于MySQL的索引文件通常很大无法常驻内存,故以文件形式存储于磁盘,于是优化MySQL检索速度很大程度上是在优化磁盘IO,即减小磁盘使用空间以及降低IO频率。动态查找树主要有:

  • 二叉查找树(Binary Search Tree)
  • 平衡二叉查找树(Balanced Binary Search Tree)
  • 红黑树(Red-Black Tree )
  • B-tree/B+tree/ B*tree (B~Tree)

前三者都是二叉树结构,随着结点的增加,会导致树的深度过大从而导致磁盘IO过于频繁,相反B-tree等使用多叉树结构,可以保持树的高度较低,减少IO次数,提升查找速度。

4. B-tree与B+tree区别

  • B+tree的内部结点并没有指向关键字具体信息的指针,故内部结点相对B-tree更小,于是需要的存储空间更小
  • B+tree所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接,B+tree只要遍历叶子节点就可以实现整棵树的遍历

5. MyISAM及InnoDB的B+tree区别

尽管MyISAM和InnoDB都以基于B+tree实现的索引,但实现方式并不一样:

  • MyISAM的索引与数据分开两个文件存储,而InnoDB的索引与数据存储在同一个文件里
  • MyISAM的辅助索引的data域存储相应记录主键的地址,而InnoDB存储主键的值

6. 联合索引的最左匹配原则测试

创建表并初始化数据

CREATE TABLE `t_question` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course` varchar(10) NOT NULL COMMENT '科目',
`grade` varchar(10) NOT NULL COMMENT '年级',
`type` varchar(10) NOT NULL COMMENT '类型',
`content` text COMMENT '题目内容',
`upload_time` datetime NOT NULL COMMENT '上传时间',
`source` varchar(50) DEFAULT NULL COMMENT '来源',
PRIMARY KEY (`id`),
KEY `Index 3` (`course`,`grade`,`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='题目表';
  • 联合索引使用不一定与顺序相关
explain select * from t_question where course='语文' and grade='六年级' and `type`='选译题';
explain select * from t_question where grade='六年级' and `type`='选译题' and course='语文';

由于MySQL查询优化器,它们使用了相同的索引

同理,以下语句也使用了相同的索引

explain select * from t_question where content like '%<p>%' and grade='六年级' and `type`='选择题' and course='语文';
explain select * from t_question where grade='六年级' and `type`='选择题' and course='语文' and content like '%<p>%';

  • 联合索引可以使用部分索引
explain select * from t_question where course='语文' and grade='六年级';
explain select * from t_question where course='语文' and `type`='选译题';

仍然可以使用联合索引,只是key_len不一样而已

  • 最左字段缺席时不能使用联合索引
explain select * from t_question where grade='六年级' and `type`='选译题';
explain select * from t_question where grade='六年级';
explain select * from t_question where `type`='选译题';

7. 常见字段已创建索引但不能使用索引的情况

  • 不符合索引的最左匹配原则
  • MySQL估计使用索引效率不及全表扫描
  • 以通配符开头的模糊查询,例如SELECT * FROM t_question WHERE course LIKE '%文'
  • NOT IN,例如SELECT * FROM t_question WHERE course NOT IN('语文')
  • !=或<>,例如SELECT * FROM t_question WHERE course!='语文'
  • OR,例如SELECT * FROM t_question WHERE course='语文' OR grade='一年级'
  • 对列进行函数运算,例如SELECT * FROM t_question WHERE substring(course, 1, 1)='文'
  • 字符型的列使用数值型的检索方式,例如SELECT * FROM t_question WHERE course=1,而SELECT * FROM t_question WHERE course='1'则可以用到索引

8. MySQL锁的引申阅读

http://blog.csdn.net/mysteryhaohao/article/details/51669741
http://jaeger.blog.51cto.com/11064196/1765906

MyISAM引擎支持表锁,而InnoDB引擎支持表锁和行锁。

  • 在使用MyISAM引擎时,读写基本可以理解为串行,但可以通过修改系统变量concurrent_insert达到并发
  • 在使用InnoDB引擎时,若执行的语句未使用索引,那么MySQL将使用表锁而非行锁,因为MySQL的行锁是通过给索引上的索引项加锁来实现的。一旦索引项加锁,操作不同行但使用同索引的数据也会因无法获得锁而阻塞

MySQL索引学习记录的更多相关文章

  1. Mysql索引学习笔记

    1.btree索引与hash索引 下列范围查询适用于 btree索引和hash索引: SELECT * FROM t1 WHERE key_col = 1 OR key_col IN (15,18,2 ...

  2. mysql 索引学习--多条件等值查询,顺序不同也能应用联合索引啦

    以前学习这一块的时候,是说:假设建立了联合索引a+b,那么查询语句也一定要是这个顺序才能应用该索引. 那么实际是怎样呢,经过mysql这么多次版本升级,相信mysql已经给我们做了某些优化. 下面是我 ...

  3. mysql索引学习

    索引用于快速找出在某列中有一特定值的行. 如果不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行. 表越大,查询数据所花费的时间越多. 如果表中查询的列有一个索引,MySQL能快速 ...

  4. MySQL巩固学习记录(一)

    mysql下载安装 一.采用图形化界面安装 (初期只安装server服务端就可以了,别的不多赘述) 二.采用压缩版安装 1.将文件解压缩到自己想要的路径 2. 添加环境变量,即mysql的bin目录 ...

  5. 4.直方图介绍和使用|MySQL索引学习

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 目录 一.导读 二.步骤 2.1 SQL语句 2.2 直方图案例 2.3 查看直方图统计信息 2.3 直方图分类 2.4 ...

  6. 从零开始学习Mysql的学习记录

    2015/06/18 16:23更新,由于QQ邮件的图片链接失效了,请在云笔记链接查看 http://note.youdao.com/share/?id=f0b2ed30a3fc8e57c381e3d ...

  7. mysql的学习记录

    1 MySQL -h localhost -u UserName -p Password-h不写,默认为localhost注意:最好先MySQL -h localhost -u UserName -p ...

  8. ”MySQL索引“学习总结

    序 learn by doing 是最快的学习方式.在百度外卖研发中心,我每天工作接触数据库方面最多的就是"索引",另外面试官在面试时也一定会考察到索引. Part 1, Expl ...

  9. mysql/mariadb学习记录——limit

    在mysql/mariadb 中可以用limit来限制查询的条数.例子如下: 1.limit后加一个参数 limit n: //选中查询所有结果中的前两条记录并返回 mysql> ; +---- ...

随机推荐

  1. fd最大值和限制

    fd的数量决定了fd的最大值 在Linux下,系统全部能够打开的fd总数为: /proc/sys/fs/file-max,取决于内存 The file-max file /proc/sys/fs/fi ...

  2. bzoj3545 Peaks 线段树合并

    离线乱搞... 也就是一个线段树合并没什么 #include<algorithm> #include<iostream> #include<cstring> #in ...

  3. redis持久化机制【十三】

    一.Redis提供了哪些持久化机制: redis的高性能是因为其所有数据都存在了内存中 ,为了使redis在重启之后数据仍然不丢失,需要将数据同步到硬盘中,这一过程就是持久化. redis支持两种方式 ...

  4. HDU 5642 King's Order【数位dp】

    题目链接: http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=677&pid=1003 题意: 求长度为n的序列 ...

  5. CentOS 7防火墙服务FirewallD指南

    CentOS 7防火墙服务FirewallD指南 作者:chszs,未经博主同意不得转载.经许可的转载需注明作者和博客主页:http://blog.csdn.net/chszs 防火墙是一种位于内部网 ...

  6. ArcGIS Python 编码问题

    吐槽一下ArcGIS自带的 Python IDE, 没有代码补全 没有函数提示 没有代码折叠 没有行号 撤销操作还有问题 字符编码还有各种问题 .........   花了2天时间才琢磨出来的经验 环 ...

  7. Django学习系列之模板

    什么是django模板 模板是一个文本,用于分离文档的表现形式和内容,模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签) 模板通常用于产生HTML 如何使用模板 创建一个Tem ...

  8. 小贝_mysql 存储过程

    存储过程 简要: 1.什么是存储过程 2.使用存储过程 一.存储过程 概念类似于函数,就是把一段代码封装起来.当要行这段代码的时候,能够通过调用该存储过程来实现.在封装的语句体里面.能够用if/els ...

  9. 关于使用Xshell远程连接启动tomcat导致图片不显示,报错Could not initialize class sun.awt.X11GraphicsEnvironment解决方案

    如果您是使用xshell远程启动tomcat,导致二维码.验证码,头像等各种图片不显示,并且打开图片链接报错Could not initialize class sun.awt.X11Graphics ...

  10. ExtAspNet从DataTable里导出Excel

    protected void btn_ToExcel_Click(object sender, EventArgs e) { Response.ClearContent(); Response.Add ...