1.索引的出现其实就是为了提高数据查询的效率,就像书的目录一样。
2.三种常见、也比较简单的数据结构,它们分别是哈希表、有序数组和搜索树。
3.哈希表是一种以键 - 值(key-value)存储数据的结构,我们只要输入待查找的键即 key,就可以找到其对应的值即 Value。
4.多个 key 值经过哈希函数的换算,会出现同一个值的情况。处理这种情况的一种方法是,拉出一个链表。
5.哈希表这种结构适用于只有等值查询的场景,做区间查询的速度是很慢的。
6.有序数组在等值查询和范围查询场景中的性能就都非常优秀,在需要更新数据的时候就麻烦了,你往中间插入一个记录就必须得挪 动后面所有的记录,成本太高。有序数组索引只适用于静态存储引擎
7.二叉搜索树的特点是:每个节点的左儿子小于父节点,父节点又小于右儿子。
8.多叉树就是每个节点有多个儿子,儿子之间的大小保证从左到右递增。二叉树是搜索效率最高的,但是实际上大多数的数据库存 储却并不使用二叉树。其原因是,索引不止存在内存中,还要写到磁盘上。
9.为了让一个查询尽量少地读磁盘,就必须让查询过程访问尽量少的数据块。那么,我们就不应该使用二叉树,而是要使用“N 叉” 树。这里,“N 叉”树中的“N”取决于数据块的大小。
10.以 InnoDB 的一个整数字段索引为例,这个 N 差不多是 1200。
11.在 InnoDB 中,表都是根据主键顺序以索引的形式存放的,这种存储方式的表称为索引组织表。
12.每一个索引在 InnoDB 里面对应一棵 B+ 树。
13.主键索引的叶子节点存的是整行数据。在 InnoDB 里,主键索引也被称为聚簇索引(clustered index)。
14.非主键索引的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。
15.基于主键索引和普通索引的查询有什么区别?
1).主键查询方式,则只需要搜索 ID 这棵 B+ 树;
2).普通索引查询方式,则需要先搜索 k 索引树,得到 ID 的值为 500,再到 ID 索引树搜索一次。这个过程称为回表.
16.一个数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。
17.从性能和存储空间方面考量,自增主键往往是更合理的选择。
18.请问没有主键的表,有一个普通索引。怎么回表?没有主键的表,innodb会给默认创建一个Rowid做主键
19.“N叉树”的N值在MySQL中是可以被人工调整的么?
1). 首先5.6以后可以通过控制page的大小间接控制;
2).计算方法,前缀索引,调整K大小;
20. 二叉搜索树更新和查询的时间复杂度均为O(logN),那么为什么不用二叉搜索树作为索引模型却选择了B+树?
1).二叉树效率高,但是树高太高,每次指针查找大概率都是触发随机磁盘读,频繁的磁盘读取使得效率变低;
2).N叉树,把整棵树的高度维持在很小范围内,同时在内存中缓存前面若干层的节点,可以极大的降低访问磁盘的次数,提高读的效率;
21.你可以想象一下一棵 100 万节点的平衡二叉树,树高 20。一次查询可能需要访问 20 个数据块。这里有点不理解,为什么树高20就是20个数据块?
1).每个叶子结点就是一个块,每个块包含两个数据,块之间通过链式方式链接。树高20的话,就要遍历20个块
2).因为是二叉树结构,每次指针查找很大概率是触发随机磁盘读(比如很难刚好碰上一个节点和他的左右儿子刚好相邻)
22.nnodb B+树主键索引的叶子节点存的是什么?B+树的叶子节点是page (页),一个页里面可以存多个行
23.索引只能定位到page,page内部怎么去定位行数据?内部有个有序数组,二分法
24.如果插入的数据是在主键树叶子结点的中间,后面的所有页如果都是满的状态,是不是会造成后面的每一页都会去进行页分裂操作,直到最后一个页申请新页移过去最后一个值?
答:不会不会,只会分裂它要写入的那个页面。每个页面之间是用指针串的,改指针就好了,不需要“后面的全部挪动
25.还有之前看到过说是插入数据如果是在某个数据满了页的首尾,为了减少数据移动和页分裂,会先去前后两个页看看是否满了,如果没满会先将数据放到前后两个页上,不知道是不是有这种情况
答:对,减为了增加空间利用率
26.非聚集索引上为啥叶子节点的value为什么不是地址,这样可以直接定位到整条数据,而不用再次对整棵树进行查询
答:这个叫作“堆组织表”,MyISAM就是这样的,各有利弊。你想一下如果修改了数据的位置的情况,InnoDB这种模式是不是就方便些.
如果你要重建索引 k,你的两个 SQL 语句可以这么写:
alter table T drop index k;
alter table T add index(k);
如果你要重建主键索引,也可以这么写:
alter table T drop primary key;
alter table T add primary key(id);
我的问题是,对于上面这两个重建索引的作法,说出你的理解。如果有不合适的,为什么,更好的方法是什么?
在评论区,有同学问到为什么要重建索引。我们文章里面有提到,索引可能因为删除,或者页分裂等原因,导致数据页有空洞,重建索引的过程会创建一个新的索引,把数据按顺序插入,这样页面的利用率最高,也就是索引更紧凑、更省空间。这道题目,我给你的“参考答案”是:重建索引 k 的做法是合理的,可以达到省空间的目的。但是,重建主键的过程不合理。不论是删除主键还是创建主键,都会将整个表重建。所以连着执行这两个语句的话,第一个语句就白做了。这两个语句,你可以用这个语句代替 : alter table T engine=InnoDB。在专栏的第 12 篇文章《为什么表数据删掉一半,表文件大小不变?》中,我会和你分析这条语句的执行流程。