可以在 Java 应用中嵌入的数据引擎看起来比较丰富,但其实并不容易选择。Redis 计算能力很差,只适合简单查询的场景。Spark 架构复杂沉重,部署维护很是麻烦。H2\HSQLDB\Derby 等内嵌数据库倒是架构简单,但计算能力又不足,连基本的窗口函数都不支持。
相比之下,SQLite 在架构性和计算能力上取得了较好的平衡,是应用较广的 Java 嵌入数据引擎。
SQLite适应常规基本应用场景
SQLite 架构简单,其核心虽然是 C 语言开发的,但封装得比较好,对外呈现为一个小巧的 Jar 包,能方便地集成在 Java 应用中。SQLite 提供了 JDBC 接口,可以被 Java 调用:
Connection connection = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement st = connection.createStatement();
st.execute("restore from d:/ex1");
ResultSet rs = st.executeQuery("SELECT * FROM orders");
SQLite 提供了标准的 SQL 语法,常规的数据处理和计算都没有问题。特别地,SQLite 已经能支持窗口函数,可以方便地实现很多组内运算,计算能力比其他内嵌数据库更强。
SELECT x, y, row_number()OVER (ORDER BY y) AS row_number FROM t0 ORDER BY x;
SELECT a, b, group_concat(b, '.') OVER (ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS group_concat FROM t1;
SQLite面对复杂场景尚有不足
SQLite 的优点亮眼,但对于复杂应用场景时还是有些缺点。
Java 应用可能处理的数据源多种多样,比如 csv 文件、RDB、Excel、Restful,但 SQLite 只处理了简单情况,即对 csv 等文本文件提供了直接可用的命令行加载程序:
.import --csv --skip 1 --schema temp /Users/scudata/somedata.csv tab1
对于其他大部分数据源,SQLite 都没有提供方便的接口,只能硬写代码加载数据,需要多次调用命令行,整个过程很繁琐,时效性也差。
以加载 RDB 数据源为例,一般的做法是先用 Java 执行命令行,把 RDB 库表转为 csv;再用 JDBC 访问 SQLite,创建表结构;之后用 Java 执行命令行,将 csv 文件导入 SQLite;最后为新表建索引,以提高性能。这个方法比较死板,如果想灵活定义表结构和表名,或通过计算确定加载的数据,代码就更难写了。
类似地,对于其他数据源,SQLite 也不能直接加载,同样要通过繁琐地转换过程才可以。
SQL 接近自然语言,学习门槛低,容易实现简单的计算,但不擅长复杂的计算,比如复杂的集合计算、有序计算、关联计算、多步骤计算。SQLite 采用 SQL 语句做计算,SQL 优点和缺点都会继承下来,勉强实现这些复杂计算的话,代码会显得繁琐难懂。
比如,某只股票最长的上涨天数,SQL 要这样写:
select max(continuousDays)-1
from (select count(*) continuousDays
from (select sum(changeSign) over(order by tradeDate) unRiseDays
from (select tradeDate,
case when price>lag(price) over(order by tradeDate) then 0 else 1 end changeSign from AAPL) )
group by unRiseDays)
这也不单是 SQLite 的难题,事实上,由于集合化不彻底、缺乏序号、缺乏对象引用等原因,其他 SQL 数据库也不擅长这些运算。
业务逻辑由结构化数据计算和流程控制组成,SQLite 支持 SQL,具有结构化数据计算能力,但 SQLite 没有提供存储过程,不具备独立的流程控制能力,也就不能实现一般的业务逻辑,通常要利用 Java 主程序的判断和循环语句。由于 Java 没有专业的结构化数据对象来承载 SQLite 数据表和记录,转换过程麻烦,处理过程不畅,开发效率不高。
前面提过,SQLite 内核是 C 程序,虽然可以被集成到 Java 应用中,但并不能和 Java 无缝集成,和 Java 主程序交换数据时要经过耗时的转换才能完成,在涉及数据量较大或交互频繁时性能就会明显不足。同样因为内核是 C 程序,SQLite 会在一定程度上破坏 Java 架构的一致性和健壮性。
对于 Java 应用来讲,原生在 JVM 上的 esProc SPL 是更好的选择。
SPL全面支持各种数据源
esProc SPL 是 JVM 下开源的嵌入数据引擎&#x