列式存储是提高数据分析计算性能的重要手段。如果数据表的总列数很多而计算涉及的列很少,采用列存就只读取需要的列即可,能够减少硬盘访问量,提高性能。而且,同一列数据往往是同一类型的,甚至有些情况取值都很接近,这样的一批数据连续存储,通常可以实施更高效的数据压缩。
但是,在实际应用中搭建一个列式数据仓库太复杂了。常用的轻量级数据库,比如 Mysql 都不支持列存。列式存储大都存在于大型 MPP 数据库中。Hadoop 也提供了列存文件格式,比如 parquet、orc 等,但仍要借助复杂的环境(Hadoop 或 spark)才能工作,架构过于沉重,虽然软件本身是开源免费的,但整体应用成本还是很高。
那么,有没有不需要繁复架构的轻量级列存技术?
开源计算引擎 esProc 的 ctx 文件就是一种很轻的列存技术。esProc 提供了简捷的编程语言 SPL 用于操作 ctx 文件。
用 SPL 可以把来自各种数据源的数据转成 ctx 实现列存,也可以把 ctx 转成其他数据源。以常见的 csv 和数据库为例:
列存文件的使用相对行存文件要稍复杂些,需要事先确定数据结构并创建相应的索引区才能写入数据,但在 SPL 支持下,这些代码仍然非常简单。
列存通常用于存储较大数据量,所以这些示例代码都使用了游标,ctx 也可以很好地支持以游标方式流式读写数据。
SPL 还为 ctx 提供了强大的计算能力,支持分段并行:
cursor 函数加上 @m 选项,就表示对 ctx 分段进行多线程并行计算,非常简单易用。
代码中文件对象 file("orders.ctx") 可以定义一次反复使用。不过游标只能计算一次,每次计算都要定义新的游标。
分段是并行计算的前提。业界普遍采用的分块列存方案,只有在总数据量很大时才有性能上的意义,一般要达到单表十亿记录、空间约在百 G 左右。规模较小的数据量就不容易获得并行计算的性能提升。ctx 采用了自创的倍增分段方案,很小的数据量且在不断追加的过程中,都可以获得良好的分段效果,保证并行计算的性能提升。
除了倍增分段,ctx 还内置了很多高性能存储方案。比如列存很难实现索引,而 ctx 使用独有的序号机制克服了这个困难。再如 ctx 利用有序存储机制,让同一列的相同值连续存放,进一步提高了列存压缩效率。
经过对比测试,ctx 读取性能几乎比 ORC 快了一倍,更是远远超过了 Parquet:
详细的测试过程和结论参见乾学院:esProc 组表,ORC,Parquet 的对比。
esProc SPL 非常轻,集成开发环境 IDE 即装即用,无需像 Hadoop 那样配置各种环境,更不需要集群:
esProc 提供了标准 JDBC 驱动,使得 ctx 很容易嵌入应用,只要将 esProc 核心 jar 包和配置文件放到 Java 应用的类路径中,ctx 文件和编写好的 SPL 脚本(比如 compute.splx)放到配置好的目录就可以调用了:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st =con.prepareCall("call computeCtx()");
st.execute();
ResultSet set = st.getResultSet();
…
对于相同的计算逻辑,SPL 代码量会比 Java 少很多。可以用 SPL 脚本实现 ctx 相关的各种复杂计算,前端应用只要接收计算结果然后展现出来就可以了。
esProc 核心 jar 包非常小,只有不到 100MB。
在报表类应用中,非常适合用 ctx 来缓存报表数据,能够获得专业列存数仓的计算性能,也不必安装配置 MPP 或 Hadoop/spark 这种重量级的产品。
SPL已开源免费,欢迎前往开源社区乾学院了解更多!
源码地址