有什么简单轻量的内存数据库技术

 

HANA/SPARK/Redis都是常见的内存数据库,但架构复杂沉重,很多场景并不适用。提到简单轻量的内存数据技术,SQLite是比较常见的,优点是体积轻巧,架构简单,可直接嵌入JAVA代码。SQLite的缺点是缺乏独立服务,不适合追求稳定的应用环境,不支持存储过程,计算能力不强,而且速度也比较慢,使用外部数据必须经过繁琐的入库过程。

简单轻量的内存数据库技术,集算器SPLSQLite好用多了。

SPL是开源的JAVA计算类库,架构简单且灵活,不仅可以直接嵌入JAVA代码,也支持独立服务。SPL有多种性能优化手段,有强大的计算能力,可直接使用外部数据。

 

SPL架构简单,无须独立服务,只要引入SPLJar包,就可以嵌入JAVA代码进行计算。先把外存数据加载到内存,比如从Oracle加载:


A

1

=connect("orcl")

2

=A1.cursor@x("select OrderID,Client,SellerID,OrderDate,Amount from orders order by OrderID")

3

=A2.memory(OrderID).index()

4

>env(orders,A3)

加载之后,就可以用SPL简单直观的语法进行计算内存。


A

1

=Orders.select(Amount>=arg1 && Amount

2

=A1.groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):s,count(1):c)

SPL提供了JDBC接口,可以被JAVA方便地集成。加载的数据量一般比较大,通常在应用的初始阶段运行一次,只须将上面的加载过程存为SPL脚本文件,在JAVA中以存储过程的形式引用脚本文件名:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
CallableStatement statement = conn.prepareCall("{call init()}");
statement.execute();
...

内存计算通常要反复执行,并发也大。较长的计算适合外置的脚本文件,修改后无须编译。对于较短的计算,可以像SQL语句那样合并成一句,写在JAVA代码中:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
Statement statement = conn.createStatement();
String arg1="1000";
String arg2="2000"
ResultSet result = statement.executeQuery(=Orders.select(Amount>="+arg1+" && Amount<"+arg2+"). groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):s,count(1):c)");
...

SPL提供了丰富的计算函数,可以轻松实现内存计算,下面是一些例子:


A

B

1

=Orders.find(arg_OrderIDList)

//多键值查找

2

=Orders.select(Amount>1000 && like(Client,\"*S*\"))

//模糊查询

3

= Orders.sort(Client,-Amount)

//排序

4

= Orders.id(Client)

//去重

5

=join(Orders:O,SellerId; Employees:E,EId).new(O.OrderID, O.Client,O.Amount,E.Name,E.Gender,E.Dept)

//关联

SPL还支持标准SQL语法,包括丰富的字符串函数和日期函数,还支持关联计算、集合计算、子查询。比如,前面的计算可以改写为下面的SQL

$select year(OrderDate) y,month(OrderDate) m, sum(Amount) s,count(1) c
from {Orders}
Where Amount>=? and Amount

 

SPL架构灵活,不仅支持嵌入计算,也支持独立服务,适合对稳定性要求严格的应用。值得一提的是,计算代码和集成方式无需改变,只要注明“服务端执行”:

Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://onlyServer=true");
Statement statement = conn.createStatement();
String arg1="1000";
String arg2="2000"
ResultSet result = statement.executeQuery(=Orders.select@m (Amount>="+arg1+" && Amount<"+arg2+"). groups(year(OrderDate):y,month(OrderDate):m; sum(Amount):s,count(1):c)");
...

 

SPL计算能力强大,可简化分步计算、有序计算、分组后计算等逻辑较复杂的计算,SQL和存储过程难以实现的计算,用SPL解决起来就很轻松。比如,找出销售额累计占到一半的前n个大客户,并按销售额从大到小排序:


A

B

2

=sales.sort(amount:-1)

/销售额逆序排序

3

=A2.cumulate(amount)

/计算累计序列

4

=A3.m(-1)/2

/最后的累计即总额

5

=A3.pselect(~>=A4)

/超过一半的位置

6

=A2(to(A5))

/按位置取值

 

在内存计算方面,除了常规的主键和索引外,SPL还提供了很多高性能的数据结构和算法支持,比大多数使用SQL的内存数据库性能好得多,且占用内存更少。需要HANA/Spark集群才能完成的运算,在SPL中常常用单机就解决了。

SPL支持并行计算,只须对原代码进行简单修改,就可以利用多核CPU提升性能。比如:


A

1

=Orders.select@m(Amount>=arg1 && Amount

2

=A1.groups(year(OrderDate):y,month(OrderDate):m;   sum(Amount):s,count(1):c)

SPL支持指针式复用,可以节省内存。SPL的数据以指针的形式参与计算,多步骤算法和不同的算法只是复用同一个表,而不像SQL那样每次都要复制记录。

SPL支持预关联技术,可以提升计算性能。SQL只能用复制记录的方式实现关联,会占用大量内存,SPL支持指针式复用,加载阶段的预关联几乎不占内存。内存计算时,可以用"."引用关联字段,更加直观方便:

=callRecord.sum(OUTID.BRANCHID.OUTCOST+INID.BRANCHID.INCOST+OUTID.AGENTID.OUTCOST+INID.AGENTID.INCOST)

SPL支持内存压缩,允许将更多的数据加载到内存,且计算代码无须修改。

 

SPL支持多种外部数据源,可避免入库或格式转换的麻烦。除了关系型数据库,还包括txt\csv\xls等文件,MongoDBHadoopredisElasticSearchKafkaCassandraNoSQL,以及WebService XMLRestful Json等多层数据。比如,将HDSF里的文件加载到内存:


A

1

=hdfs_open(;"hdfs://192.168.0.8:9000")

2

=hdfs_file(A1,"/user/Orders.csv":"GBK")

3

=A2.cursor@t()

4

=hdfs_close(A1)

5

=A3.memory(OrderID).index()


6

>env(orders,A5)


SPL支持内外存混合计算。有些数据太大,无法放入内存,但又要与内存表共同计算,这种情况可利用SPL实现内外存混合计算。比如,主表orders已加载到内存,大明细表orderdetail是文本文件,下面进行主表和明细表的关联计算:


A

1

=file("orderdetail.txt").cursor@t()

2

=orders.cursor()

3

=join(A1:detail,orderid ; A2:main,orderid)

4

=A3.groups(year(main.orderdate):y; sum(detail.amount):s)