Btree索引
基础
为了加快点查速度,需要在数据库中引入索引(特别是OLTP场景)。索引的最基础的实现有2种:Hash和Tree。PG诞生于内存不足,且磁盘IO为主要瓶颈的时代,因此面向磁盘优化的BTree就是当仁不让的选择。
[ Root ]
|
+--------+--------+ root is in memory
| |
[ Internal ] [ Internal ] read each [node] from disk
| |
+----+----+ +----+----+ until leaf
| | | |
[Leaf]<->[Leaf] <-> [Leaf]<->[Leaf]
其内部实现参看GP中的BTree实现,这我之前为GP社区写的一篇详细介绍,其实现和pg9.6完全一致。
再补充记录一些要点:
- 通过opclass/opfamily来支持多类型,有点类似C++中的traits
- 与表数据一样,索引也需要WAL支持
- 索引不区分MVCC多版本,因此这里存在一系列优化,比如HOT
- 索引操作需要考虑(高性能的)并发控制:blink树,postgres中的实现参考
- 如何删除索引键以及何时释放空间,也参考如上的link
在pg最近的几个大版本(12~18)中对btree进行了许多改进,但是结构和操作上没有大的变化,包括了:
- 优化性能/空间:并行索引创建(CIC),索引键deduplication,bottom-up删除,异步IO支持等等
- 优化器适配:支持更多的query场景,比如in(…)
- 运维:监控索引创建进度,更多的explain项等
Discussion
Btree索引主要服务于oltp场景,而对于olap场景更多的是采用bitmap(GP独有的),brin等索引。
对比与pg的heap+btree,常见的数据组织形式还有LSM方式。《DDIA》中有一节对它们进行了比较:主要关注读写放大上的差异。
另外如果是全内存数据库(索引也全部加载在内存中),那么可以考虑其他更高效的索引,比如Hash索引,Trie树索引(ART in DuckDB)。
对于Btree的现代改进,可以参考sigmod25的最新论文《B-Trees Are Back》以及其参考文献,论文解读。
Questions:
- postgres中的CREATE INDEX CONCURRENTLY (CIC)并不阻塞读写操作,那么它是如何实现的?
提示:实际上存在短暂阻塞操作