一个 SQL 查询即可访问 Java 中的多个数据源(来自 oracle、excel、sql server)

我需要开发可以使用一个数据源(等)从多个数据源(等)获取数据的应用程序。例如:Oracle, Excel, Microsoft Sql ServerSQL query

 SELECT o.employeeId, count(o.orderId) 
    FROM employees@excel e. customers@microsoftsql c, orders@oracle o 
    WHERE o.employeeId = e.employeeId and o.customerId = c.customerId 
    GROUP BY o.employeeId;

此 sql 和数据源必须由 java 程序动态更改。我的客户希望在我的应用程序的Web界面中同时编写和运行来自不同数据库和存储的类似sql的查询,并按分组,具有,计数,求和等。其他要求是性能和重量轻。

我找到了这种方式来做到这一点(如果我错了,我看到了什么缺点,请修复我):

  1. Apache Spark缺点:繁重的解决方案,对大数据更好,如果您需要在不缓存Spark的情况下获取最新信息,则速度较慢),

  2. SQL Server中的分布式查询Oracle的数据库链接Microsoft SQL Server的链接服务器Excel的Power Query) - 缺点:Java程序动态更改数据源的问题以及使用Excel的问题,

  3. Prestodb缺点:重度解决方案,对大数据更好),

  4. Apache Drill缺点:相当年轻的解决方案,一些不是最新的odbc驱动程序的问题和工作时的一些错误),

  5. Apache Calcite(Apache Drill使用的ligth框架,缺点:相当年轻的解决方案),

  6. 从数据源手动联接(缺点:开发正确联接需要大量工作,结果集中的“分组依据”,找到最佳执行计划等)

也许,您知道任何其他方式(使用免费的开源解决方案)或从您的经验中给我任何关于上述方式的建议?任何帮助将不胜感激。


答案 1

UnityJDBC 是一个商业 JDBC 驱动程序,它包装多个数据接收器,并允许您将它们视为同一数据库的一部分。它的工作原理如下:

定义一个“架构文件”来描述每个数据库。架构文件类似于以下内容:

...
<TABLE>
    <semanticTableName>Database1.MY_TABLE</semanticTableName>
    <tableName>MY_TABLE</tableName>
    <numTuples>2000</numTuples>
 <FIELD>
    <semanticFieldName>MY_TABLE.MY_ID</semanticFieldName>
    <fieldName>MY_ID</fieldName>
    <dataType>3</dataType>
    <dataTypeName>DECIMAL</dataTypeName>
    ...

您还有一个中央“源文件”,它引用所有架构文件并提供连接信息,如下所示:

<SOURCES>
    <DATABASE>
        <URL>jdbc:oracle:thin:@localhost:1521:xe</URL>
        <USER>scott</USER>
        <PASSWORD>tiger</PASSWORD>
        <DRIVER>oracle.jdbc.driver.OracleDriver</DRIVER>
        <SCHEMA>MyOracleSchema.xml</SCHEMA>
    </DATABASE>
    <DATABASE>
        <URL>jdbc:sqlserver://localhost:1433</URL>
        <USER>sa</USER>
        <PASSWORD>Password123</PASSWORD>
        <DRIVER>com.microsoft.sqlserver.jdbc.SQLServerDriver</DRIVER>
        <SCHEMA>MySQLServerSchema.xml</SCHEMA>
    </DATABASE> 
</SOURCES>

然后,您可以使用 来允许 Java 代码运行跨数据库联接的 SQL,如下所示:unity.jdbc.UnityDriver

String sql = "SELECT *\n" +
"FROM MyOracleDB.Whatever, MySQLServerDB.Something\n" +
"WHERE MyOracleDB.Whatever.whatever_id = MySQLServerDB.Something.whatever_id";
stmt.execute(sql);

因此,看起来UnityJDBC提供了您需要的功能,但是,我不得不说,任何允许用户执行任意SQL以连接不同数据库的表的解决方案都听起来像是使您的数据库屈服的配方。我实际上会针对您的要求类型推荐的解决方案是从所有数据源执行 ETL 过程到单个数据仓库,并允许用户查询该数据仓库;如何定义这些流程和数据仓库对于堆栈溢出问题来说肯定太宽泛了。


答案 2

其中一个合适的解决方案是DataNucleus平台,它具有JDO,JPA和REST API。它支持几乎所有的RDBMS(PostgreSQL,MySQL,SQLServer,Oracle,DB2等)和NoSQL数据存储,如基于Map,基于Graph,基于Doc等,数据库Web服务,LDAP,文档如XLS,ODF,XML等。

或者,您可以使用EclipseLink,它也支持RDBMS,NoSQL,数据库Web服务和XML。

通过使用作为 JDO API 一部分的 JDOQL,可以满足具有一个查询来访问多个数据存储的要求。这两种解决方案都是开源的,相对轻量级和高性能。

我为什么建议这个解决方案?

  • 从您的要求中可以理解,数据存储将是您的客户选择,您不是在寻找大数据解决方案。
  • 您更喜欢轻量级且性能高昂的开源解决方案。
  • 考虑到您的使用案例,您可能需要一个具有多语言持久性行为的数据管理平台,该平台能够根据您/客户的用例利用多个数据存储。

阅读更多有关多语言持久性的信息

https://dzone.com/articles/polyglot-persistence-future

https://www.mapr.com/products/polyglot-persistence


推荐