除了 DBLink 还有啥可以做跨库运算的
和DBLink原理类似的有Federated Database和Linked Server,这类数据库组件的配置都很复杂,而且大多数计算要先把数据取到本地,不能充分利用远程数据库的计算能力。Calcite是支持跨库运算的JAVA计算库,优点是配置简单,集成方便,代码开源,缺点是成熟度不高,很多计算函数都不支持。Scala是大数据计算语言,也有跨库运算的能力,优点是比较成熟,性能也不错,缺点是架构复杂沉重,代码繁琐冗长,数据超出内存时容易发生故障。
做跨库运算,SPL是个更好的选择。
SPL是开源的JAVA计算库,不仅架构轻便,配置简单,函数丰富,具有方便集成的JDBC接口,还可以充分利用数据库的计算能力,并稳定计算超出内存的数据。
SPL可以充分利用数据库的计算能力。远程数据库先执行SQL或存储过程,SPL再将数据量较小的计算结果取到本地,最后进行跨库运算。比如对MySQL和Oracle进行内关联:
A |
|
1 |
=mysql1.query("select SellerId, sum(Amount) subtotal from Orders group by SellerId") |
2 |
=orcl.query("select EId,Name from employees") |
3 |
=join(A1:O,SellerId; A2:E,EId).new(O.Name:name, O.Dept:dept, E.subtotal:amt) |
SPL提供了丰富的计算函数,可以用简单直观的代码完成跨库后的计算。比如,跨库运算后按页取记录,其中p_Size和P_No是参数:
A |
|
3 |
…//跨库运算 |
4 |
=A3.to(p_Size*(p_No-1),p_Size*p_No) |
SPL提供了JDBC接口,方便被JAVA程序调用。比如将上面的算法存为SPL脚本文件,在JAVA中以存储过程的形式调用SPL:
…
Class.forName("com.esproc.jdbc.InternalDriver");
Connection conn =DriverManager.getConnection("jdbc:esproc:local://");
CallableStatement statement = conn.prepareCall("{call pageQuery(?, ?)}");
statement.setObject(1, 10);
statement.setObject(2, 3);
statement.execute();
...
再举几例:
A |
B |
|
3 |
… |
|
4 |
=A2.select(amt>1000 && like(dept,\"*S*\")) |
//查询 |
5 |
=A2.sort(dept,-amt)" |
//排序 |
6 |
=A2 .id(dept) |
//去重 |
7 |
=A2.groups(dept;sum(amt)) |
//分组汇总 |
对于超出内存的数据,SPL提供了游标机制,不仅代码简短,而且稳定可靠。比如,表Employees和Orders都是大表,分属不同的数据库,下面先跨库关联,再分组汇总:
A |
|
1 |
=orcl.cursor("select EId, Dept from Employees order by EId") |
2 |
=mysql1.cursor("select SellerId, Amount from Orders order by SellerId") |
3 |
=joinx(A2:O,SellerId; A1:E,EId) |
4 |
=A3.groups(E.Dept;sum(O.Amount)) |
上面代码利用了有序归并进行关联,性能也更好。
对于多个同构的数据库,SPL支持分库间的跨库运算和语法精炼的并行计算:
A |
B |
C |
|
1 |
=[connect("mysql1"),connect("mysql2"), |
/连接多个mysql |
|
2 |
select * from orders |
/SQL |
|
3 |
fork A1 |
=A3.query@x(A2) |
/并行执行SQL |
4 |
=A3.conj() |
/合并结果 |
除了数据库,SPL也支持CSV/XLS等文件数据源和多种NoSQL,以及不同数据源/数据库之间的混合计算。
英文版