Table of Contents |
---|
...
文件结构
每个数据文件 TsFile 在内存中对应一个对象 TsFileResource,主要包含以下信息
- 版本号
- 时间索引:将此 TimeIndex:将此 TsFile 中所有时间序列的路径 默认按照 (root - 倒数第二层)分组,每组为一个索引条目(包含:路径、起始时间、终止时间)
- PlanIndex:raft Raft日志段:raft 中一个 TsFile 文件对应的 Raft 日志的起始和终止下标
- ModificationPath:墓碑文件路径(如果存在墓碑文件)
示例:
如果 TsFile 文件中的各个序列的时间范围如下所示:
root.sg.d1.s1, 1, 10
root.sg.d1.s2, 1, 15
root.sg.d2.s1, 1, 10
root.sg.d3.s1, 5, 10
则 TimeIndex 为
root.sg.d1, 1, 15
root.sg.d2, 1, 10
root.sg.d3, 5, 10
可以看到,按设备记录只是其中一种分组方式。当设备过多时(几十万量级)内存增长过快,因此可以针对不同层次的基数设计不同的分组方式。
TimeIndex 设计方案
一、TsFileResource及接口设计修改目标
2. 目标:
(1) 总体目标:目前tsfile采用一对一的索引方式,每个tsfile都有一个索引文件TsFileResource,tsfile文件内的信息(开始时间、结束时间等)都保存在TsFileResource中。
由于TsFileResource常驻内存中,
本次针对TsFileResouce的改进总目标为可以支持更多的设备,将 resource 中的设备起止时间移出,单独在文件的时间索引模块进行管理,
且可以支持不同实现方式(如每个文件对应一个时间范围索引条目)。每个数据文件在内存中还以 TsFileResource 对象进行管理。
(2) 阶段1目标 —— 接口化:区分【文件句柄TsFileResource】和【文件索引TimeIndex】,将TsFileResource中开始时间、结束时间等字段移至TimeIndex中。
3. 实现方案:TimeIndex仅作为 TsFileResource 中的一个对象,全部接口均由 TsFileResource 调用,不向外暴露;
TsFileResource 的已有接口不变。后续“实现”的全部修改仅针对 ITimeIndex。
二、阶段1详细设计:新增和修改的数据结构
具体而言,涉及到数据结构如下:
1. DeviceTimeIndex (后续“实现”的全部修改仅针对 TimeIndex)
...
protected long[] startTimes; // 开始时间列表
protected long[] endTimes; // 结束时间列表,未封口则为 Long.MIN_VALUE
protected Map<String, Integer> deviceToIndex; // device设备名 => 开始 / 结束时间列表index
2. 第二步的修改(后续)涉及到【封口文件句柄SealedTsfileResource】和【未封口文件句柄UnsealedTsfileResource】
因为封口文件句柄需要的字段较少,未封口文件句柄可以继承封口文件句柄;文件封口时再转化为封口文件句柄。
3. 总结
(1) 第一步接口化(本次)的修改中,可以从TsFileResource中转移走的字段:
...
protected long[] startTimes; // 开始时间列表
protected long[] endTimes; // 结束时间列表,未封口则为 Long.MIN_VALUE
protected Map<String, Integer> deviceToIndex; // device设备名 => 开始 / 结束时间列表index
(2) 目前TsFileResource文件句柄保留的功能和字段:
...
Map<String, String> cachedDevicePool // for reducing the String number in memory
File file // tsfile
TsFileProcessor processor 【未封口】
ModificationFile modFile // modification file
boolean closed【未封口】
boolean deleted【未封口】
boolean isMerging
TsFileLock tsFileLock
List<ChunkMetadata> chunkMetadataList // 【未封口】chunk metadata list of unsealed tsfile. Only be set in a temporal TsFileResource in a query process.
List<ReadOnlyMemChunk> readOnlyMemChunk // 【未封口】mem chunk data. Only be set in a temporal TsFileResource in a query process.
TimeseriesMetadata timeSeriesMetadata // 【未封口】get TimeseriesMetadata of unsealed file
List<TsFileResource> upgradedResources // 【升级】generated upgraded TsFile ResourceList used for upgrading v0.9.x/v1 -> 0.10/v2
UpgradeTsFileResourceCallBack upgradeTsFileResourceCallBack // 【升级】load upgraded TsFile Resources to storage group processor used for upgrading v0.9.x/v1 → 0.10/v2
boolean isSeq // 【升级】indicate if this tsfile resource belongs to a sequence tsfile or not used for upgrading v0.9.x/v1 -> 0.10/v2
TsFileResource originTsFileResource // 【未封口】current tsfile resource is a snapshot of the originTsFileResource. When we want to used the lock, we should try to acquire the lock of originTsFileResource
long maxPlanIndex // for cluster, max index of plans executed within this TsFile
long minPlanIndex // for cluster, min index of plans executed within this TsFile
- 墓碑文件路径:如果存在墓碑文件则记录
4. TsFileResource 文件结构
VERSION_NUMBER = 1 (1 byte) timeIndexType = 0 FileTimeIndex / 1 DeviceTimeIndex (1 byte) timeIndex (ITimeIndex)
maxPlanIndex (long) minPlanIndex (long) modFileName (String) |
各个字段用处
- 版本号
- IoTDB 版本升级时识别不同版本的 TsFileResource 结构
- 时间索引
- 查询时根据 TsFileResource 中的时间索引判断某个 TsFile 是否可能包含待查数据
- 跨文件空间数据合并时,根据 TsFileResource 的时间索引判断哪些文件需要被合并
- TTL 线程根据 TsFileResource 的时间索引定期检查 TsFile 是否整个过期,可以完全删除
- Raft 日志段
- 墓碑文件路径