实验背景
之前测试写入单个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.4111661911011 | 172.48751544952393 | 168.86190605163574 |
time(ms) | 907.1112 | 1292.0548 | 1174.4459 |
乙:
ORC | (write)TsFile | (writeAlign)TsFile | |
---|---|---|---|
Total file size(M): | 7643.75181388855 | 1726.471918106079 | 1689.685453414917 |
time(ms) | 13756.197 | 20822.018 | 20691.305 |
可以看出在原来的TsFile在该测试场景下确实写入速度要明显低于ORC文件的写入速度,但ORC文件的大小较大。
分析:
通过阅读ORC文件的写入源码和TsFile文件的写入源码:
梳理出如下几点不同:
- ORC文件底层写入时是按列写入的,每一列对应一个TreeWriter进行写入;TsFile在写入时是按行写,遍历每一行,每一列对应一个ChunkWriter进行写入;
- ORC文件是每一个batch写完后再检查内存条件,决定是否进行刷盘;TsFile是每写一个Point就检查一遍;
- ORC文件针对于double类型是类似于Plain编码的方式,TsFile对于double类型进行了编码;
- ORC只在调用close()时再强制刷盘,TsFile在flush chunkGroup时的会调用flush()强制刷盘;
- ORC文件数据写入ByteBuffer中,每256Kb的ByteBuffer会进行压缩,每64M写入outputStream中,TsFile是每一个Page(默认是达到1024*1024 point才进行压缩,每128M写入outputStream)
- 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编码) | |
---|---|---|---|---|---|---|---|
763.4111661911011 | 172.48751544952393 | 172.48751544952393 | 768.2062187194824 | 168.86190605163574 | 168.6880750656128 | 764.375714302063 | |
time(ms) | 907.1112 | 1292.0548 | 1331.6311 | 1694.6985 | 1174.4459 | 1177.4089 | 1511.809 |
乙:
ORC | (write)TsFile | (write)TsFile(改了flush) | (write)TsFile(改了flush和去掉double编码) | (writeAlign)TsFile | (writeAlign)TsFile(改了flush) | (writeAlign)TsFile(改了flush和去掉double编码) | |
---|---|---|---|---|---|---|---|
7643.75181388855 | 1726.471918106079 | 1726.471918106079 | 7687.583155632019 | 1689.685453414917 | 1687.3616762161255 | 7646.913384437561 | |
time(ms) | 13756.197 | 20822.018 | 19787.156 | 22170.355 | 20691.305 | 21361.916 | 22144.346 |
可以发现,改了flush几乎没什么影响,但去掉double编码不仅文件变大,写入更慢。
在排除上述几点之后,最后更改了第一点将TsFile写入,改成按列写入,按列遍历,测试结果如下所示:
改后writeAlign写入条件下,TsFile文件稍微变小是因为writeAlign下把原来每写入一个Point就 checkPageSizeAndMayOpenANewPage
那段代码变成批量写完后才调用一次造成的。(也就是将如下代码移到双重循环写入数据后进行,减小了一些元数据的大小)
if (checkPageSizeAndMayOpenANewPage()) {
writePageToPageBuffer();
}
甲:
writeAlign
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 763.4111661911011 | 168.86190605163574 | 168.6880750656128 |
time(ms) | 907.1112 ms | 1174.4459 ms | 842.77026 |
write
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 763.4111661911011 | 172.48751544952393 | 172.48751544952393 |
time(ms) | 907.1112 ms | 1292.0548 ms | 985.80145 ms |
乙:
writeAlign
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 7643.75181388855 | 1689.685453414917 | 1687.3616762161255 |
time(ms) | 13756.197 | 20691.305 ms | 12617.888 |
write
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 7643.75181388855 | 1726.471918106079 | 1726.471918106079 |
time(ms) | 13756.197 | 20822.018 ms | 10056.04 |
可以发现,改完之后写入速度明显提升,与ORC基本没区别,甚至快一些。
由此可见,按列写对于底层的局部性原理比较友好,cache命中快,在该测试中对于写入的影响占绝大因素。
最后是额外补充了一个在SSD上写入的测试
SSD
甲:
write
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 763.4111661911011 | 172.48751544952393 | 172.48751544952393 |
time(ms) | 356.96976 ms | 1191.7109 ms | 683.7835 ms |
writeAlign
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 763.4111661911011 | 168.86190605163574 | 168.6880750656128 |
time(ms) | 356.96976 ms | 1042.2322 ms | 699.66364 ms |
乙:
write
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 7643.75181388855 | 1726.471918106079 | 1726.471918106079 |
time(ms) | 6591.9214 ms | 19148.916 ms | 9042.89 ms |
writeAlign
ORC | TsFile | TsFile(改) | |
---|---|---|---|
Total file size(M): | 7643.75181388855 | 1689.685453414917 | 1687.3616762161255 |
time(ms) | 6591.9214 ms | 20342.082 ms | 11089.69 ms |
通过观察实验结果可以发现,其相对原来写入速度提升将近一倍,但还是比ORC要慢一些,暂时不清楚为什么ORC在SSD下写入速度会有所提升?