在数据库中,索引是一种排好序,高效获取数据的数据结构。贴上一个学习数据结构的网站:www.cs.usfca.edu/~galles/vis...
一. 为什么数据库要通过索引来查询数据,一条条数据比对不就好了.
在实际查询过程中,比如select * from table where name='张三'
。这条语句在没有索引的情况下,他会逐行比对,每次从磁盘获取一条数据比对一次,直到找到张三这条数据。从磁盘读取数据时比较慢,毕竟一次磁盘IO是低效的,这个时候索引就诞生了。
二. 为什么Mysql偏偏选择B+树作为索引数据结构,而不是二叉树,红黑树,B树。
- 如果是二叉树,是什么样子。比如主键就是一种索引,在自增的情况下,从1开始自增将会呈现下图所示,仅仅只有7个数据,二叉树的高度就有7层。如果是几百几千万条记录,树的高度也会是几百几千万。这样显然是不合适,如Sql语句
select * from table where id='7'
,这样得查找7次才能找到所需要的值。

- 如果是红黑树,同样以主键自增为例,7个数据的树的高度是3层,比二叉树好一些,节点的数据过多时,它会发生一次自平衡,所以他也叫做平衡二叉树,在面对几百万几千万数据时,树的高度也会达到几十或者几百万。同样不能作为索引的数据结构

- B树行不行呢,由于B+树和B树有些像,所以放在一起比较,我们来看看。上面的是B树,下面的是B+树,注意mysql的B+树经过改良后的,他的数据结构不是呈现下面的这个样子


-
mysql的B+树,它是B树的一个变种,上图是B+树,下图是B树。这俩者有什么区别,
B+树非叶子节点是没有数据的,他是为了存储更多索引的才这么设计,叶子节点包含了所有索引字段,叶子节点之间用指针链接,并且从左到右依次递增,这也是为什么他可以支持范围查询。以主键索引为例也叫聚集索引,叶子节点的上包含了这一条记录的所有数据。
B树从左到右依次递增,但是叶子节点之间是没有指针的,所有的索引元素是不重复的这是它的一个特点
这就回到了B树能不能作为索引的数据结构的问题上来,反过来先看B+树的表现如何,B+树的一个节点相当于一个一页,大概有16K,用
show GLOBAL STATUS LIKE 'Innodb_page_size'
这条Sql语句可以看到16384.不推荐改这个值,这个是mysql经过很多次优化得出的结果。假设一个字段字段8个字节,6个字节的指针地址(指向下一个节点),16K除以14个字节。那么一页可以存放1170个元素,下一个节点也是1170个元素,假设有三层,叶子节点1一个元素1KB,则有16个元素,则1170乘以1170乘以16等于俩千多万条数据,这样看来俩千多万条数据三层树的结构,加上B+树的特性刚好合适作为索引的数据结构。至于B树合适吗,叶子节点和非叶子节点都包含数据,那么在一页当中,存放的索引肯定就比B+树要少很多,树的高度就不止三层这么少了,仅仅这一条就作为索引的数据结构就不太合适。


三. 什么是回表查询
数据库innodb存储引擎,除了主键索引之外,还的索引,非主键索引,也就是二级索引,比如联合索引,当然联合索引也选择了B+树作为索引结构,它的叶子节点存储的是主键,当select语句没有覆盖联合索引的字段时,数据库会获取到叶子节点中的主键数据,再通过主键去主键的B+树上去查询,这种操作叫做回表,主键索引也叫做聚集索引。至于为什么二级索引叶子节点不像主键索引那样,存放所有数据,那得多放三四份甚至更多,这会浪费更多磁盘空间,同时插入一条数据的时候,为了一致性,主键索引和二级索引全部插完成,才能讲它插入完成,否则可能会出问题。
四. 为什么推荐innodb必须建主键,并且是整型的自增主键
当不建主键会发生什么,mysql当中,它会在所有列当中,选一列都不相等的一列来组织那棵B+树,如果没有一列是被选中,会自己建一列隐藏列来维护唯一ID,将其来组织B+树,数据库的资源是很宝贵的,这样的事情让mysql来做是不合适,增加mysql的工作。
主键最好是整型的是因为在插入数据的时候它会比大小,如果非整型它会一个个的字符比大小,这样肯定是整型比非整型的要快得多。如果插入的是整型数据不是自增的,mysql的B+树是一个排好序的数据结构,为了维持排好序,它会发生一次或者多次自平衡,比大小,努力使新加入的数据放到一个合适的位置,直到按照一定的顺序排列。