h2database 是应用Java 编写的开源数据库,兼容ANSI-SQL89。既实现了惯例基于 BTree 的存储引擎,又反对日志构造存储引擎。性能十分丰盛(死锁检测机制、事务个性、MVCC、运维工具等),数据库学习十分好的案例。
本文实践联合实际,通过BTree 索引的设计和实现,更好的了解数据库索引相干的知识点以及优化原理。
BTree 实现类h2database 默认应用的 MVStore 存储引擎,如果要应用 基于 BTree 的存储引擎,须要特地指定(如下示例代码 jdbcUrl)。
以下是惯例存储引擎(BTree 构造) 相干的要害类。
org.h2.table.RegularTableorg.h2.index.PageBtreeIndex (SQL Index 本体实现)org.h2.store.PageStore (存储层,对接逻辑层和文件系统)BTree 的数据结构能够从网上查到具体的形容和解说,不做过多赘述。
须要特地阐明的是:PageStore。咱们数据查问和优化要害的缓存、磁盘读取、undo log都是由 PageStore 实现。能够看到具体的文档和残缺的实现。
BTree add index entry 调用链提供索引数据新增的调用链。同样的,索引的删除和查问都会波及到,不便 debug 参考。org.h2.command.dml.Insert#insertRows (Insert SQL 触发数据和索引新增)org.h2.mvstore.db.RegularTable#addRow (解决完的数据Row, 执行新增)org.h2.index.PageBtreeIndex#add (逻辑层减少索引数据)org.h2.index.PageDataIndex#addTry (存储层减少索引数据)org.h2.index.PageDataLeaf#addRowTry (存储层新增实现)// 示例代码// CREATE TABLE city (id INT(10) NOT NULL AUTO_INCREMENT, code VARCHAR(40) NOT NULL, name VARCHAR(40) NOT NULL);public static void main(String[] args) throws SQLException { // 留神:MV_STORE=false,MVStore is used as default storage Connection conn = DriverManager.getConnection("jdbc:h2:~/test;MV_STORE=false", "sa", ""); Statement statement = conn.createStatement(); // CREATE INDEX IDX_NAME ON city(code); 增加数据触发 BTree 索引新增 // -- SQL 实例化为:IDX_NAME:16:org.h2.index.PageBtreeIndex statement.executeUpdate("INSERT INTO city(code,name) values('cch','长春')"); statement.close(); conn.close();}Code Insight联合上述的示例代码,从索引新增的流程实现来理解BTree 索引的个性以及应用的注意事项。从底层实现剖析索引的运行,对 SQL 索引应用和优化有进一步意识。表增加数据 public void addRow(Session session, Row row) { // MVCC 管制机制,记录和比对以后事务的 id lastModificationId = database.getNextModificationDataId(); if (database.isMultiVersion()) { row.setSessionId(session.getId()); } int i = 0; try { // 依据设计规范,indexes 必定会有一个汇集索引(h2 称之为scan index)。① for (int size = indexes.size(); i < size; i++) { Index index = indexes.get(i); index.add(session, row); checkRowCount(session, index, 1); } // 记录以后 table 的数据行数,事务回滚后会相应递加。 rowCount++; } catch (Throwable e) { try { while (--i >= 0) { Index index = indexes.get(i); // 对应的,如果产生任何异样,会移除对应的索引数据。 index.remove(session, row); } } throw de; }}① 同Mysql InnoDB 数据存储一样, RegularTable 必有,且只有一个汇集索引。以主键(或者隐含自增id)为key, 存储残缺的数据。
...