前一篇中简单的写了下关于索引的删除,这一篇中完整的介绍整个数据删除步骤。
1.根据ID查找索引数据(主要是获取具体数据地址,有点像数据库中的根据索引进行回表)
2.根据索引的数据偏移查找具体的空间ID(在第二篇中介绍了整个系统的存储结构,存储空间是分块的,一个数据对象可能存储在一个“逻辑空间”中,也有可能存储在多个存储空间中,取决于对象的大小)。
3.根据ID去管理文件中查找具体的空间存储,采用跳跃表的方式进行查找
4.回收数据空间,这里其实就是把空间的使用状态设为“NEW”,也就是未使用状态,下次分配的时候可以根据状态进行判断当前空间是使用状态还是未使用状态而进行重新分配。
5.回收索引,可重复使用,也是设置索引的状态
入口代码的实现,这里只贴入口代码,每一步都会有比较具体的实现,比如说如何根据ID查找索引,如何检索数据地址,以后会讲到:
public void run() {
long startTime = System.currentTimeMillis();
//从索引文件中查找索引,主要是可以获取数据空间的偏移量
DataOffset offset = indexReader.read(id);
if (offset != null) {
List<Integer> storageIdList = new ArrayList<Integer>();
//查询存储空间的ID,是一个List
dataReader.readStorage(storageIdList, offset);
//根据id列表取存储文件中查找具体的空间ID。
List<DataObject> storageList = dataFileManager.read(storageIdList);
//回收数据空间,这里其实就是把空间的使用状态设为“NEW”,也就是未使用
dataFileManager.gc(storageList);
IndexStruct indexStruct = new IndexStruct();
indexStruct.setKey(offset.getIndexId());
indexStruct.setDataStartPos(offset.getStartPos());
//回收索引,可重复使用,也是设置索引的状态
indexWriter.gc(offset.getIndexPos(), indexStruct);
}
System.out.println("[DataRemovePerThread.run]timeDiff="+(System.currentTimeMillis()-startTime));
}
这是整个删除的操作的序列图,其实是上面一段代码用图的方式表现出来:
再用一张流程图会更加清楚的看到具体的删除流程:
总结:这里并未考虑事务性,在这几步中都可能有异常情况而导致数据操作失败,这样的情况下理论上是需要进行回滚。当然在我的实现中并未把事务纳入其中,所以也并未做这方面的现实。这里两个地方检索是用到了跳跃表,索引的检索不言自明,前面有博文已经讲到过。空间地址的搜索也是用跳跃表进行实现,这样可以加快检索速度而提高性能。