MySQL中B+树索引的使用
1) 不同应用中B+树索引的使用
对于OLTP应用,由于数据量获取可能是其中一小部分,建立B+树索引是有异议时的
对OLAP应用,情况比较复杂,因为索引的添加应该是宏观的而不是微观的。
2) 联合索引
对表上多个列进行索引。联合索引的创建方法与多个索引创建的方法一样。不同之处在于有多个索引页
CREATE TABLE t(
a INT,
b INT,
PRIMARY KEY(a),
KEY idx_a_b(a,b)
)ENGINE=INNODB
从本质上来说,联合索引也是一棵B+树,不同的联合索引的键值的数量不是1,而是大于等于2。
讨论一下由2个整数列组成的联合索引,分别为a,b

可以看到键值是顺序的,通过叶子节点可以逻辑上顺序地读出所有的数据,即(1,1)(1,2)(2,1)(2,4)(3,1)(3,2)。数据按(a,b)顺序存放
因此对于查询SELECT * FROM TABLE WHERE a = 1 and b=2,显然是可以使用(a,b)联合索引的。对于单列a查询SELECT * FROM TABLE WHERE a = 1,也是可以用到这个(a,b)索引,但是对于b列SELECT * FROM TABLE WHERE b = 2则不可以使用B+树索引。可以发现叶子节点上b列的值为1 2 1 4 1 2 不是顺序的。因此对于b列的查询是使用不到(a,b)的索引
联合索引的第二个好处是已经对第二个键值进行排序处理。例如在很多情况下,需要对某个用户的购物情况进行查询,并且按照时间排序最后取出最近三次的购物记录,使用联合索引可以避免多一次的排序操作。因为索引本身在叶子节点已经排序了。
CREATE TABLE buy_log(
userid INT UNSIGNED NOT NULL,
buy_date DATE
)ENGINE=INNODB;
INSERT INTO buy_log VALUES(1,'2009-01-01');
INSERT INTO buy_log VALUES(2,'2009-01-01');
INSERT INTO buy_log VALUES(3,'2009-01-01');
INSERT INTO buy_log VALUES(1,'2009-02-01');
INSERT INTO buy_log VALUES(3,'2009-02-01');
INSERT INTO buy_log VALUES(1,'2009-03-01');
INSERT INTO buy_log VALUES(1,'2009-04-01');
ALTER TABLE buy_log ADD KEY(userid);
ALTER TABLE buy_log ADD KEY(userid,buy_date);
建立了两个索引做比较。都包含userid。
SELECT * FROM buy_log WHERE userid=2;
查看优化器的选择

可以看到两个索引都可以使用。但优化器最终使用了userid,因为该索引的叶子节点包含单个键值。所以理论上一个页能存放的记录应该更多
假定要取出userid=1的最近3次记录
EXPLAIN SELECT * FROM buy_log WHERE userid=1 ORDER BY buy_date DESC LIMIT 3;

这次优化器使用了(userid,buy_date)的联合索引userid_2 因为在这个联合索引中buy_date已经排序了。根据该联合索引取出数据,无须在对buy_date做一次额外的排序操作。若强制使用userid索引
EXPLAIN SELECT * FROM buy_log FORCE INDEX(userid) WHERE userid=1 ORDER BY buy_date DESC LIMIT 3;

可以看到Using filesort,即需要额外的一次排序操作才能完成查询。显然是对buy_date排序。因为索引userid中的buy_date是未排序的
联合索引(a,b)其实是根据列a,b进行排序的,故此下面语句可以直接使用联合索引得到结果
EXPLAIN SELECT * FROM TABLE WHERE a=1 ORDER BY b;
对于联合索引(a,b,c) 也可以直接通过联合索引得到结果
EXPLAIN SELECT * FROM TABLE WHERE a=1 and b = 1 ORDER BY c; EXPLAIN SELECT * FROM TABLE WHERE a=1 ORDER BY b;
但是对于下面语句,就不能得到结果了,需要执行一次filesort排序操作因为(a,c)并未排序
EXPLAIN SELECT * FROM TABLE WHERE a=1 ORDER BY c;
3) 覆盖索引
InnoDB存储引擎支持覆盖索引,即从辅助索引中就可以查询到记录,而不需要查询聚集索引中的记录。使用覆盖索引的一个好处是辅助索引不包含整行记录的所有信息,故其大小远小于聚集索引。因此可以减少大量的IO操作
对于InnoDB存储引擎的辅助索引,由于其包含了主键信息,因此其叶子节点存放的数据为(parimary key1,parimary key2,...key1,key2,...)例如,下面语句都可仅使用一次辅助联合索引来完成查询
SELECT key2 FROM table WHERE key1=xxx; SELECT primary key2,key2 FROM table key1=xxx; SELECT primary key1,key2 FROM table key1=xxx; SELECT primary key1,primary key2,key2 FROM table key1=xxx;
覆盖索引的另一个好处是对某些统计问题而言,如上的buy_log,要进行如下查询
SELECT COUNT(*) FROM buy_log;
InnoDB存储引擎并不会选择通过查询聚集索引来进行统计。由于buy_log还有辅助索引,而辅助索引远小于聚集索引。选择辅助索引可以减少IO操作。

如图显示。possible_keys是NULL,但是实际执行优化器却选择了userid,而列Extra的Using index就是代表优化器选择了覆盖索引的操作
此外,在通常情况下,(a,b)的联合索引,一半是不可以选择列b中所谓的查询条件,但是如果是统计操作,并且是覆盖索引的。则优化器会进行选择
EXPLAIN SELECT COUNT(*) FROM buy_log WHERE buy_date>='2011-01-01' AND buy_date<'2011-02-01';

表buy_log有(userid,buy_date)联合索引,这里只根据b进行了条件查询,一般情况下,是不能进行该联合索引的。但这条SQL语句查询是统计操作。并且可以利用覆盖索引的信息。因此优化器是会选择联合索引的。
MySQL中B+树索引的使用的更多相关文章
- 面试官:为什么Mysql中Innodb的索引结构采取B+树?
前言 如果面试官问的是,为什么Mysql中Innodb的索引结构采取B+树?这个问题时,给自己留一条后路,不要把B树喷的一文不值.因为网上有些答案是说,B树不适合做文件存储系统的索引结构.如果按照那种 ...
- SQL优化 MySQL版 - B树索引详讲
SQL优化 MySQL版 - -B树索引详讲 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 为什么要进行SQL优化呢?很显然,当我们去写sql语句时: 1会发现性能低 2.执行时间太 ...
- MySQL中的聚集索引和辅助索引
MySQL中的聚集索引和辅助索引 当你定义一个主键时,innodb存储引擎就把他当做聚集索引 如果你没有定义一个主键,则innodb定位到第一个唯一索引,且改索引的所有列值均为非空,就将其当做聚集索引 ...
- MySQL的B+树索引和hash索引的区别
简述一下索引: 索引是数据库表中一列或多列的值进行排序的一种数据结构:索引分为聚集索引和非聚集索引,聚集索引查询类似书的目录,快速定位查找的数据,非聚集索引查询一般需要再次回表查询一次,如果不使用索引 ...
- MySQL中的联合索引学习教程
MySQL中的联合索引学习教程 这篇文章主要介绍了MySQL中的联合索引学习教程,其中谈到了联合索引对排序的优化等知识点,需要的朋友可以参考下 联合索引又叫复合索引.对于复合索引:Mysql从左到 ...
- 高性能MySQL中的三星索引
高性能MySQL中的三星索引 我对此提出了深深的疑问: 一星:相关的记录指的是什么??(相关这个词很深奥,“相关部门”是什么部门) 二星:如果建立了B-Tree(B+Tree)索引,数据就有序了.三星 ...
- InnoDB 中 B+ 树索引的分裂
数据库中B+树索引的分裂并不总是从页的中间记录开始,这样可能会导致空间的浪费,例如下面的记录: 1, 2, 3, 4, 5, 6, 7, 8, 9 插入式根据自增顺序进行的,若这时插入10这条记录后需 ...
- Mysql中使用树的设计
原来一直使用id与 parent_id结合的办法设计树,最近发现有些问题: 1.查询此结点下所有子结点的需求. 2.查询此结点上所有父结点的需求. 这些需求在oracle和sql server中可以使 ...
- 如何检查mysql中建立的索引是否生效的检测方法及相关参数说明
所使用的mysql函数explain语法:explain < table_name >例如: explain select * from t3 where id=3952602;expla ...
随机推荐
- Linux下默认的目录介绍
目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - /bin 该目录存放着系统最常用的最重要的命令,相当于DOS ...
- 关于struts、spring 和 hibernate的说明
struts 是 web 框架 (jsp/action/actionfrom) hibernate 是 orm框架,处于持久层. spring 是容器框架,用于配置bean,并维护bean之间关系的框 ...
- redis实践一些要注意的事项
不要放垃圾数据,及时清理无用数据实验性的数据和下线的业务数据及时删除; key尽量都设置过期时间对具有时效性的key设置过期时间,通过redis自身的过期key清理策略来降低过期key对于内存的占用, ...
- linux查找yum和rpm安装路径
linux查找yum和rpm安装路径 转:https://jingyan.baidu.com/article/86112f1378bf282737978730.html
- 使用pycharm手动搭建python语言django开发环境(四) django中buffer类型与str类型的联合使用
在django中,如果用到buffer类型时,buffer的编码格式是utf-8类型.使用str()进行转为字符串类型会异常. 异常会有如下提示:'ascii' codec can't decode ...
- MFC invalidate和RedrawWindow区别
Invalidate()函数是强制系统进行重画,但是不一定就马上进行重画.因为Invalidate()只是通知系统,此时的窗口已经变为无效.强制系统调用WM_PAINT,而这个消息只是Post就是将该 ...
- hash和encrypt区别及应用_转
转自:哈希(Hash)与加密(Encrypt)的基本原理.区别及工程应用 0.摘要 今天看到吉日嘎拉的一篇关于管理软件中信息加密和安全的文章,感觉非常有实际意义.文中作者从实践经验出发,讨论了信息管理 ...
- 对象中prototype与__proto__与从cinstructor的作用和区别
首先先要知道prototype什么时间才会有 只有在创建函数的时候,每当函数创建的时候才会原型prototype,还有一个constructor,这个不是函数独有的,对象也有 下面就来说说对象prot ...
- Win10中配置jdk之后javac无法运行
环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等. 环境变量是在操作系统中一个具有特定名字的对象,它包 ...
- 有向图 加最少的边 成为强连通分量的证明 poj 1236 hdu 2767
poj 1236: 题目大意:给出一个有向图, 任务一: 求最少的点,使得从这些点出发可以遍历整张图 任务二: 求最少加多少边 使整个图变成一个强连通分量. 首先任务一很好做, 只要缩点 之后 求 ...