Наилучшая практика для копирования результатов запроса из нескольких объединенных таблиц одной базы данных в другую базу данных? - PullRequest
0 голосов
/ 08 мая 2018
  • У меня есть несколько объединенных таблиц с большим количеством данных в одной базе данных postgreSQL (версия 9.6.4) под названием «sourceDB».
  • Мне нужно запросить все эти таблицы и скопировать результаты из 'sourceDB' во вторую (пустую) базу данных postgreSQL (также версии 9.6.4) с именем 'destinationDB', которая не имеет схемы базы данных, но должна иметь та же схема базы данных, как 'sourceDB'.
  • Обе базы данных находятся в одной хост-системе и должны управляться через приложение JAVA.

То, что я до сих пор пробовал, это:

  1. Определите схему базы данных 'sourceDB'.
  2. Запустите оператор «CREATE TABLE IF NOT EXISTS ...» для всех существующих таблиц «sourceDB» в «destinationDB», чтобы убедиться, что обе базы данных имеют одинаковую схему базы данных. Это работает очень хорошо!
  3. Запустите запрос БД (SELECT DISTINCT ...) для каждой таблицы (в «sourceDB»), чтобы получить данные, и после этого запустите для каждой таблицы функцию «copyTableData», чтобы скопировать результаты (через INSERT INTO) в « destinationDB ':

JAVA-код:

  String[] tables = new String[]{
                    "table1",
                    "table2_table4",
                    "table3_addresses",
                    "table4",
                    "table5",
                    "table6",
                    "table7",
                    "table8",
                    "table9",
                    "table10",
                    "table11",
                    "table12"
  };

  int counter = 0;

  for( String table : tables ){
        int copyProcess = 100/tables.length*counter;

        if (counter == 0){
              System.out.println(importApp.getDateTime() + 
                    "Initiating Import - Importing table '" + table + "'");
        } else {
              System.out.println(importApp.getDateTime() + 
                    copyProcess + " % completed - Importing table '" + table + "'");
        }

        getDataFromSrcDB = "SELECT DISTINCT " + table + ".* " +
              "FROM table1 " +
                    "FULL JOIN table2_table4 " +
                      "ON table2_table4.d_id=table1.d_id " +
                    "FULL JOIN table3_addresses " +
                      "ON table3_addresses.d_id=table2_table4.d_id " +
                    "FULL JOIN table4 " +
                      "ON table4.p_id=table2_table4.p_id " +
                    "FULL JOIN table5 " +
                      "ON table5.d_id=table1.d_id " +
                    "FULL JOIN table6 " +
                      "ON table6.d_id=table1.d_id " +
                    "FULL JOIN table7 " +
                      "ON table7.d_id=table1.d_id " +
                    "FULL JOIN table8 " +
                      "ON table8.d_id=table1.d_id " +
                    "FULL JOIN table9 " +
                      "ON table9.d_id=table1.d_id " +
                    "FULL JOIN table10 " +
                      "ON table10.id=table6.id " +
                    "FULL JOIN table11 " +
                      "ON table11.d_id=table1.d_id " +
                    "FULL JOIN table12 " +
                      "ON table12.a_id=table3_addresses.a_id " +
                    "WHERE ST_Intersects(ST_MakeEnvelope(" +
                      myApp.minLong + "," +
                      myApp.minLat + "," +
                      myApp.maxLong + "," +
                      myApp.maxLat + ",4326), geom :: GEOMETRY) OR " +
                    "ST_Intersects(ST_MakeEnvelope(" +
                      myApp.minLong + "," +
                      myApp.minLat + "," +
                      myApp.maxLong + "," +
                      myApp.maxLat + ",4326), CAST(table5.location AS GEOMETRY))";

                      myApp.copyTableData(dbConnOnSrcDB, dbConnOnDestDB, getDataFromSrcDB, table);
                      counter++;
            }
  1. Теперь скопируйте результаты запроса в 'destinationDB' (через INSERT INTO):

JAVA-код:

  public void copyTableData(Connection dbConnOnSrcDB, Connection dbConnOnDestDB, String sqlQueryOnSrcDB, String tableNameOnDestDB) throws SQLException {

    try (

        PreparedStatement prepSqlStatmOnSrcDB = dbConnOnSrcDB.prepareStatement(sqlQueryOnSrcDB);

        ResultSet sqlResultsFromSrcDB = prepSqlStatmOnSrcDB.executeQuery()

    ) {
        ResultSetMetaData sqlMetaResults = sqlResultsFromSrcDB.getMetaData();

        // Stores the query results
        List<String> columnsOfQuery = new ArrayList<>();

        // Store query results
        for (int i = 1; i <= sqlMetaResults.getColumnCount(); i++)
            columnsOfQuery.add(sqlMetaResults.getColumnName(i));

        try (
            PreparedStatement prepSqlStatmOnDestDB = dbConnOnDestDB.prepareStatement(
                "INSERT INTO " + tableNameOnDestDB +
                     " (" + columnsOfQuery.stream().collect(Collectors.joining(", ")) + ") " +
                        "VALUES (" + columnsOfQuery.stream().map(c -> "?").collect(Collectors.joining(", ")) + ")")
        ) {

            final int batchSize = 1000;
            int count = 0;
            while (sqlResultsFromSrcDB.next()) {
                for (int i = 1; i <= sqlMetaResults.getColumnCount(); i++) {
                    prepSqlStatmOnDestDB.setObject(i, sqlResultsFromSrcDB.getObject(i));
                }

                prepSqlStatmOnDestDB.addBatch();
                if (++count % batchSize == 0) {
                    prepSqlStatmOnDestDB.executeBatch();
                }
            }

            // Insert remaining records
            prepSqlStatmOnDestDB.executeBatch();

            prepSqlStatmOnDestDB.close();
            prepSqlStatmOnSrcDB.close();
        }
    }
  }

Моя проблема в том, что я не настолько опытен в (Postgres) SQL, поэтому я не уверен, что мой подход хорош (эффективен / эффективен), соответственно, какова на самом деле лучшая практика для достижения этого?

Другая проблема заключается в том, что первый вызов функции copyTableData (в терминах 'table1') работает довольно хорошо, но если функция copyTableData вызывается во второй раз (для 'table2' или 'table3', или ...) Я получаю исключение JAVA, что есть строка, которая уже содержит значения (ноль, ноль, ноль, нуль, ноль, ноль). Я не уверен, как это интерпретировать ...:

  • Как вы думаете, проблема во втором INSERT INTO в том, что у INSERT INTO есть проблемы с уже существующими первичными ключами, такими как d_id, из-за первого вызова функции copyTableData (в терминах 'table1')?
  • Или у INSERT INTO действительно есть проблемы с нулевыми значениями?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...