深入浅出索引(上篇)
创建时间:2021年11月11日11:17:03
编辑时间:2021年11月16日09:33:58
文章目录
——————————————————————————————
索引基本数据类型
问:有哪几种索引基本数据类型,分别有什么特点,时间复杂度如何?
答:
1、哈希链表:不支持区间查询
插入 | 等值查询 | 区间查询 |
---|---|---|
O(1) | O(1)(无碰撞情况下) | O(N) |
2、有序数组:随机插入成本高
插入 | 等值查询 | 区间查询 |
---|---|---|
O(N)(最坏情况下) | O(log(N)) | O(log(N)) |
3、搜索树:IO设计减少磁盘访问
插入 | 等值查询 | 区间查询 |
---|---|---|
O(log(N)) | O(log(N)) | O(log(N)) |
(关于数据结构特点如果有不了解,可以查阅相关资料,例如《数据结构(Java语言描述)》)
问:为什么使用N叉树?
答:减少磁盘IO次数。PG:17亿数据量的自增主键(bigint)树(排除数据空洞情况),树高4
计算:( 16kb / (8 + 6)B ) ^ 3 = 17亿,树高为4。(默认的数据页大小16k,bigint长度8B,索引指向子树指针6B)
问:不同的引擎对同样的索引数据类型的实现原理一致吗?举个例子。
答:不一样。MyINSAM引擎的B+树主键树(.MYI)叶节点的域值存放的是数据地址(.MYD),辅助索引同理;Innodb引擎的B+树的数据文件(.ibd)又是索引文件,主键树的叶节点域值存放完整的数据记录,而辅助索引叶节点的域值存放的是主键索引值。
InnoDB 索引及维护
问:索引模型有哪几种?
答:聚簇索引和二级索引,其中,主键索引、隐式自增索引、唯一索引为聚簇索引,其他普通索引(联合索引等)为二级索引。
问:基于主键索引和普通索引的查询有什么区别?
答:后者需要回表查询。
问:Innodb维护索引的流程如何?
答:在插入值、删除(空间利用率抵达最低阈值)时做维护。
插入时,维护有序性,可能伴随页分裂,产生空洞;合并时,是页分裂的逆过程;
问:什么是页分裂?有什么影响?
答:某个数据页已满,需要插入数据以保证有序性时,该数据页分裂出另外一个数据页,一部分数据移动到另一个数据页。
频繁的页分裂会影响性能,并且浪费空间。
问:怎么减少页分裂?
答:考虑采用自增主键。因为自增主键本身保持有序性,其写入是追加写而非中间插入,可以减少聚簇索引树的索引页分裂。
问:选用主键时有什么考虑?
答:个人不建议使用业务字段(业务变动层面),建议采用占用字节较小的类型(空间层面:非主键索引树的叶节点存放主键索引值)。
如果要使用业务字段做主键,尽量确保整张表只有一个索引。
问:怎么处理页分裂的”空洞“问题?
答:重建索引。重建主键索引树时,会将非主键索引树全部重建,注意以下场景
alter table T drop primary key;
alter table T add primary key(id);
alter table t engine = Innodb;
前面两句是矛盾的,不论哪一句都会额外再重建一次索引,建议使用最后一句(原因在第13篇会有详细解释)。