实验背景

之前测试写入单个TsFile和ORC文件,发现写入ORC明显快于写单个TsFile

实验配置

写入数据的scheme: <long(time), double(值)>

写入数据的两组,为书写方便以甲、乙命名。

批量写,batchSize = 5000

甲:1个设备100个测点,每个测点插入100w行

乙:1个设备1000个测点,每个测点插入100w行

实验结果与分析

HDD

甲:


ORC(write)TsFile(writeAlign)TsFile
Total file size(M):763.4111661911011172.48751544952393168.86190605163574
time(ms)907.11121292.05481174.4459

乙:


ORC(write)TsFile(writeAlign)TsFile
Total file size(M):7643.751813888551726.4719181060791689.685453414917
time(ms)13756.19720822.01820691.305

可以看出在原来的TsFile在该测试场景下确实写入速度要明显低于ORC文件的写入速度,但ORC文件的大小较大。

分析:

通过阅读ORC文件的写入源码和TsFile文件的写入源码:

梳理出如下几点不同:

  1. ORC文件底层写入时是按列写入的,每一列对应一个TreeWriter进行写入;TsFile在写入时是按行写,遍历每一行,每一列对应一个ChunkWriter进行写入;
  2. ORC文件是每一个batch写完后再检查内存条件,决定是否进行刷盘;TsFile是每写一个Point就检查一遍;
  3. ORC文件针对于double类型是类似于Plain编码的方式,TsFile对于double类型进行了编码;
  4. ORC只在调用close()时再强制刷盘,TsFile在flush chunkGroup时的会调用flush()强制刷盘;
  5. ORC文件数据写入ByteBuffer中,每256Kb的ByteBuffer会进行压缩,每64M写入outputStream中,TsFile是每一个Page(默认是达到1024*1024 point才进行压缩,每128M写入outputStream)
  6. ORC文件每一列都只会存一次,其效果更接近于TsFile的writeAlign;TsFile如果不是writeAlign,则time列会保存多次。

第2、5点改了之后,几乎同上面结果差不多;第六点,其实在实验过程中time列的写入影响很小。

下面是改了flush以及去掉double编码后的效果,发现写入速度甚至反而下降,其测试结果如下所示:

甲:


ORC(write)TsFile(write)TsFile(改了flush)(write)TsFile(改了flush和去掉double编码)(writeAlign)TsFile(writeAlign)TsFile(改了flush)(writeAlign)TsFile(改了flush和去掉double编码)
Total file size(M):763.4111661911011172.48751544952393172.48751544952393768.2062187194824168.86190605163574168.6880750656128764.375714302063
time(ms)907.11121292.05481331.63111694.69851174.44591177.40891511.809

乙:


ORC(write)TsFile(write)TsFile(改了flush)(write)TsFile(改了flush和去掉double编码)(writeAlign)TsFile(writeAlign)TsFile(改了flush)(writeAlign)TsFile(改了flush和去掉double编码)
Total file size(M):7643.751813888551726.4719181060791726.4719181060797687.5831556320191689.6854534149171687.36167621612557646.913384437561
time(ms)13756.19720822.01819787.15622170.35520691.30521361.91622144.346

可以发现,改了flush几乎没什么影响,但去掉double编码不仅文件变大,写入更慢。

在排除上述几点之后,最后更改了第一点将TsFile写入,改成按列写入,按列遍历,测试结果如下所示:

改后writeAlign写入条件下,TsFile文件稍微变小是因为writeAlign下把原来每写入一个Point就 checkPageSizeAndMayOpenANewPage 那段代码变成批量写完后才调用一次造成的。(也就是将如下代码移到双重循环写入数据后进行,减小了一些元数据的大小)

if (checkPageSizeAndMayOpenANewPage()) {
 writePageToPageBuffer();
}

甲:

writeAlign

ORCTsFileTsFile(改)
Total file size(M):763.4111661911011168.86190605163574168.6880750656128
time(ms)907.1112 ms1174.4459 ms842.77026
write

ORCTsFileTsFile(改)
Total file size(M):763.4111661911011172.48751544952393172.48751544952393
time(ms)907.1112 ms1292.0548 ms985.80145 ms

乙:

writeAlign

ORCTsFileTsFile(改)
Total file size(M):7643.751813888551689.6854534149171687.3616762161255
time(ms)13756.19720691.305 ms12617.888
write

ORCTsFileTsFile(改)
Total file size(M):7643.751813888551726.4719181060791726.471918106079
time(ms)13756.19720822.018 ms10056.04

可以发现,改完之后写入速度明显提升,与ORC基本没区别,甚至快一些。

由此可见,按列写对于底层的局部性原理比较友好,cache命中快,在该测试中对于写入的影响占绝大因素。


最后是额外补充了一个在SSD上写入的测试

SSD

甲:

write

ORCTsFileTsFile(改)
Total file size(M):763.4111661911011172.48751544952393172.48751544952393
time(ms)356.96976 ms1191.7109 ms683.7835 ms
writeAlign

ORCTsFileTsFile(改)
Total file size(M):763.4111661911011168.86190605163574168.6880750656128
time(ms)356.96976 ms1042.2322 ms699.66364 ms

乙:

write

ORCTsFileTsFile(改)
Total file size(M):7643.751813888551726.4719181060791726.471918106079
time(ms)6591.9214 ms19148.916 ms9042.89 ms
writeAlign

ORCTsFileTsFile(改)
Total file size(M):7643.751813888551689.6854534149171687.3616762161255
time(ms)6591.9214 ms20342.082 ms11089.69 ms

通过观察实验结果可以发现,其相对原来写入速度提升将近一倍,但还是比ORC要慢一些,暂时不清楚为什么ORC在SSD下写入速度会有所提升?

  • No labels