Один SQL-запрос для доступа к нескольким источникам данных в Java (от oracle, excel, sql-сервера)

Мне нужно разработать приложение, которое может получать данные из нескольких источников данных ( Oracle, Excel, Microsoft Sql Server и т. д.), используя один SQL 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. Мои клиенты хотят писать и запускать sql-like query из другой базы данных и хранилища одновременно с group by, having, count, sum и т. д. в веб-интерфейсе моего приложения. Другими требованиями являются производительность и легкость.

Я нахожу этот способ сделать это (и какие недостатки я вижу, пожалуйста, поправьте меня, если я ошибаюсь):

  1. Apache Spark (недостатки: тяжелое решение, больше подходит для больших данных, медленный, если вам нужно получать актуальную информацию без ее кэширования в Spark),

  2. Распределенные запросы на сервере SQL (ссылка на базу данных Oracle, Связанный сервер Microsoft SQL Server, Power Query Excel) - недостатки< /strong>: проблема с динамическим изменением источников данных программой java и проблема с работой с Excel,

  3. Prestodb (недостатки: тяжелое решение, лучше для больших данных),

  4. Apache Drill (недостатки: довольно молодое решение, некоторые проблемы с не последним odbc драйвера и некоторые баги при работе),

  5. Apache Calcite (легкий фреймворк, используемый Apache Drill, недостатки: довольно молодое решение еще),

  6. Выполняйте объединение из источников данных вручную (недостатки: много работы по разработке правильного объединения, "группировка по" в наборе результатов, поиск наилучшего плана выполнения и т. д.)

Может быть, вы знаете какой-нибудь другой способ (используя бесплатные решения с открытым исходным кодом) или дадите мне какой-нибудь совет из своего опыта о способах, описанных выше? Любая помощь будет принята с благодарностью.


person Slava Vedenin    schedule 20.01.2016    source источник
comment
SSIS и собирать данные в центральном месте (SQL Server), а затем запросите его.   -  person Lukasz Szozda    schedule 20.01.2016
comment
Проблема в том, что не каждый раз мы можем использовать базу данных Microsoft SQL Server, в некоторых случаях у нас есть только база данных Oracle, Excel и, например, mySql.   -  person Slava Vedenin    schedule 20.01.2016
comment
Вы можете вставить в любую другую БД в качестве места назначения, например MySQL/Postgresql/Oracle.   -  person Lukasz Szozda    schedule 20.01.2016
comment
Используйте инструмент бизнес-аналитики, такой как Qlikview, для сопоставления данных из разных СУБД, а затем объединяйте их на уровне извлечения Qlikview.   -  person Matt    schedule 20.01.2016
comment
Вы можете вставить в любую другую БД в качестве места назначения, например MySQL/Postgresql/Oracle. Да, это помогает в некоторых случаях, но нам нужно объединить две очень большие таблицы из Oracle и SQL-сервера, это невозможно.   -  person Slava Vedenin    schedule 20.01.2016
comment
Почему это нужно делать в SQL-запросе? Почему нельзя запросить каждый источник данных отдельно, а затем объединить результаты?   -  person TMN    schedule 22.01.2016
comment
Потому что мне нужно, например, выполнить групповую функцию (группировать по), используя эти объединенные результаты. Мои клиенты хотят написать любой sql из любой базы данных (с наличием, группировкой, порядком, суммой(), подсчетом() и т. д.). Конечно, я могу попытаться сделать свой собственный анализатор SQL для объединенных результатов и создать собственный оптимизатор планов выполнения, однако для этого потребуется много работы.   -  person Slava Vedenin    schedule 22.01.2016
comment
Сам мало что об этом знаю, но есть UnityJDBC.   -  person heenenee    schedule 22.01.2016
comment
О, спасибо. Почему вы не пишете про UnityJDBC в ответ? Это может быть тот же ответ, что мы находим...   -  person Slava Vedenin    schedule 22.01.2016
comment
@ViacheslavVedenin Я ответил в соответствии с просьбой, хотя UnityJDBC не является моим настоящим ответом. Удачи тебе с твоим проектом.   -  person heenenee    schedule 24.01.2016
comment
Apache Metamodel может быть решением для ваших требований. metamodel.apache.org   -  person Sagar Gandhi    schedule 28.01.2016


Ответы (8)


Одним из подходящих решений является платформа DataNucleus с API-интерфейсами JDO, JPA и REST. Он поддерживает почти все СУБД (PostgreSQL, MySQL, SQLServer, Oracle, DB2 и т. д.) и хранилища данных NoSQL, такие как карты, графики, документы и т. д., веб-службы баз данных, LDAP, документы, такие как XLS, ODF, XML и т. д.

В качестве альтернативы вы можете использовать EclipseLink, который также поддерживает СУБД, NoSQL, веб-службы баз данных и XML.

При использовании JDOQL, который является частью JDO API, будет выполнено требование наличия одного запроса для доступа к нескольким хранилищам данных. Оба решения имеют открытый исходный код, относительно легкие и производительные.

Почему я предложил это решение?

  • Из вашего требования понятно, что хранилище данных будет вашим выбором клиента, и вы не ищете решение для больших данных.
  • Вы предпочитаете решения с открытым исходным кодом, легкие и производительные.
  • С учетом вашего варианта использования вам может потребоваться платформа управления данными с режимом постоянства полиглота, которая может использовать несколько хранилищ данных в зависимости от ваших/клиентских вариантов использования.

Чтобы узнать больше о сохранении полиглота

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

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

person Hari    schedule 26.01.2016

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>

Затем вы можете использовать unity.jdbc.UnityDriver, чтобы позволить вашему Java-коду запускать SQL, который объединяется между базами данных, например:

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 обрабатывает все ваши источники данных в единое хранилище данных и позволяет пользователи запрашивают это; как определить эти процессы, и ваше хранилище данных определенно слишком широкое для вопроса о стеке.

person heenenee    schedule 24.01.2016
comment
Я согласен. Это требует хранилища данных для хранения всей информации. - person Denis Tulskiy; 28.01.2016
comment
Поскольку ETL не может быть возможным для всех. Вы знаете производительность этого решения в среднем? - person jDub9; 11.06.2019

SQL связан с системой управления базами данных. Для SQL Server потребуются другие операторы SQL, отличные от сервера Oracle SQL.

Я предлагаю использовать JPA. Он полностью независим от вашей системы управления базами данных и делает разработку на Java намного более эффективной.

Недостатком является то, что нельзя объединить несколько систем баз данных с JPA из коробки (как в отношении 1: 1 между SQL Server и Oracle SQL server). Однако вы можете создать несколько EntityManagerFactories (по одному для каждой базы данных) и связать их вместе в своем коде.

Плюсы для JPA в этом сценарии:

  • писать независимые запросы JPQL от системы управления базами данных
  • уменьшает требуемый код Java

Минусы JPA:

  • вы не можете связать объекты из разных баз данных (например, в отношениях 1: 1)
  • вы не можете запрашивать несколько баз данных одним запросом (объединение таблиц из разных баз данных в group by или аналогичном)

Больше информации:

person slartidan    schedule 22.01.2016
comment
Спасибо, я знаю, что такое JPA. Но знаете ли вы какое-либо решение JPA, которое может одновременно использовать объекты из разных баз данных? Например, можно ли использовать отношение «один к одному» из таблицы Oracle и таблицы MySql? - person Slava Vedenin; 22.01.2016
comment
Да спасибо. Проблема в том, что мои клиенты хотят писать и запускать SQL-подобные запросы из разных баз данных и хранилищ одновременно с группировкой, наличием, подсчетом, суммированием и т. д. в веб-интерфейсе моего приложения. Это сложно сделать с помощью ручного слияния объектов jpa (необходимо написать синтаксический анализатор sql, оптимизатор плана оптимизации и построить объекты jpa во время выполнения). Но, большое спасибо за вашу помощь! - person Slava Vedenin; 22.01.2016
comment
@ViacheslavVedenin Я абсолютно согласен - JPA - не очень хорошее решение, если вы хотите group by по нескольким базам данных. Я хотел бы оставить этот ответ для других пользователей с аналогичными требованиями, но в вашем случае JPA, вероятно, не правильный выбор. - person slartidan; 22.01.2016
comment
Просто пытаюсь добавить свою мысль к этому решению. Может быть полезно. Используйте JPA. Реализуйте factory на уровне взаимодействия с базой данных (DAO) кода и для каждого типа базы данных напишите собственные запросы к базе данных. Это может помочь вам, если вы знаете, из каких баз данных вы собираетесь получать данные. В этом подходе вы можете получать данные из разных фабрик, применяя логику, а затем обрабатывать их. - person Rahul; 28.01.2016
comment
@Rahul Спасибо за ваше предложение. Обычно я стараюсь избегать DAO и нативных запросов и вместо этого использую чистый JPA. При использовании собственных запросов в этом случае вы потеряете независимость от базового диалекта sql. - person slartidan; 28.01.2016

Я бы рекомендовал presto и calcite. производительность и легкость не всегда идут рука об руку.

  • presto: довольно много проверенных способов использования, как вы сказали, «больших данных». хорошо работает масштабируется. Я не совсем понимаю, что конкретно означает легкий вес, если одним из них является требование меньшего количества машин, вы определенно можете масштабировать меньше в соответствии с вашими потребностями.

  • calcite : встроен во множество библиотек анализа данных, таких как drill kylin phoenix. делает то, что вам нужно, "подключение к нескольким БД" и, самое главное, "легкий вес"

person zinking    schedule 29.01.2016

Имея опыт работы с некоторыми кандидатами (Apache Spark, Prestodb, Apache Drill), я выбрал Prestodb. Несмотря на то, что он в основном используется в больших данных, я думаю, что его легко настроить, и он поддерживает (почти) все, что вам нужно. В Интернете доступно множество ресурсов (включая запуск в Docker), а также отличные документация и активное сообщество, а также поддержка двух компаний (Facebook и Netflix).

person Istvan    schedule 29.01.2016

Несколько баз данных на нескольких серверах от разных поставщиков Самый сложный случай — это когда базы данных находятся на разных серверах, и на некоторых серверах работает разное программное обеспечение баз данных. Например, база данных клиентов может размещаться на компьютере X в Oracle, а база данных заказов может размещаться на компьютере Y с Microsoft SQL Server. Даже если обе базы данных размещены на машине X, но одна находится в Oracle, а другая в Microsoft SQL Server, проблема остается той же: каким-то образом информация в этих базах данных должна быть разделена между разными платформами. Многие коммерческие базы данных поддерживают эту функцию с помощью некоторой формы объединения, компонентов интеграции или связывания таблиц (например, IBM, Oracle, Microsoft), но поддержка в базах данных с открытым исходным кодом (HSQL, MySQL, PostgreSQL) ограничена.

Существуют различные методы решения этой проблемы:

  • Table Linking and Federation - связать таблицы из одного источника в другой для запроса
  • Custom Code - написать код и несколько запросов для ручного объединения данных
  • Data Warehousing/ETL — извлечь, преобразовать и загрузить данные в другой источник
  • Mediation Software - напишите один запрос, который будет переведен посредником для извлечения необходимых данных
person Santosh    schedule 29.01.2016

Может быть идея заработной платы. Попробуйте использовать Apache Solr. Используйте различные источники данных и импортируйте данные в Apache solr. Когда данные доступны, вы можете писать различные запросы, индексируя их.

Это поисковая платформа с открытым исходным кодом, которая гарантирует, что ваш поиск будет быстрее.

person BValluri    schedule 22.01.2016
comment
Спасибо, очень интересная идея - person Slava Vedenin; 22.01.2016
comment
Вы пробовали этот вариант. Это решило вашу проблему - person BValluri; 27.01.2016

Вот для чего нужна структура Hibernate. Hibernate имеет собственный язык запросов HQL, в основном идентичный SQL. Hibernate действует как промежуточное ПО для преобразования запроса HQL в запросы, специфичные для базы данных.

person Raju Rao    schedule 27.01.2016