【问题标题】:Inserting a MySQL result-set, retrieved from a select query?插入从选择查询中检索的 MySQL 结果集?
【发布时间】:2016-11-23 18:57:23
【问题描述】:

我在 服务器 x 上有一个 MySQL 数据库,另一个在 服务器 y 上。

我正在尝试从位于服务器 x 上的名为 testx 的表中获取记录,并将 INSERT 它们放入名为 testy 的表中。所以我所做的是执行SELECT 语句并将其存储到resultset 中。然后我尝试在resultsetwhile 循环中迭代INSERT 语句。这是我的示例代码:

private static void cloneTableAndAlter() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException, InterruptedException {
        Connection connForSource = getConnectionForSource();
        Connection connForTarget = getConnectionForTarget();

        if (connForSource != null && connForTarget != null) {
            try {
                Statement st = connForSource.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                        java.sql.ResultSet.CONCUR_READ_ONLY);

                String selectStatement = "SELECT field1, field2 FROM dbx.testx where time between ('2016-09-01 00:00:00') and ('2016-09-03 23:59:59');";

                String insertStatement = "INSERT INTO testy(" + "field1," + "field2)" + 
                        "VALUES(?,?) " +
                        "ON DUPLICATE KEY UPDATE field1 = VALUES(field1);"; <----field1 is a unique key but not primary

                st.setFetchSize(Integer.MIN_VALUE);

                ResultSet resultSetForSelect = st.executeQuery(selectStatement);
                PreparedStatement preparedStatement = connForTarget.prepareStatement(insertStatement);
                int count = 0;
                while (resultSetForSelect.next()) {
                    ++count;
                    TableDetails tableDetails = setTableDetails(resultSetForSelect); <--- i'm getting the value from the resultset and setting it to my DTO class.
                    getTableDetails(preparedStatement, tableDetails); <--- setting the values back during the insert from the DTO
                    preparedStatement.executeUpdate();
                    System.out.println(count + "rows affected");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

注意:源表(testx)有超过一百万条记录。

我可以插入,但我觉得插入有点慢,每秒插入 45-50 次。我要去哪里迟钝?

有什么方法可以优化此操作并增加插入次数,或者这是插入大型数据集的本质吗?

任何帮助都将不胜感激。

【问题讨论】:

  • 我会从衡量需要时间的事情开始。是读,还是写,或两者兼而有之。如果读取速度很慢,也许您只需要时间列上的索引。如果写入速度很慢,您可以使用批处理来发送一批插入,而不是一次执行一个插入。如果两者兼有,则可能是网络问题。
  • 感谢@JBNizet,注意到了。 “只需要时间列上的索引”是什么意思?
  • 您的 qquery 在 testx 表中查找在 rwo 值之间存在时间的行。如果您没有在该时间列上定义数据库索引,那么 MySQL 将进行全表扫描以查找您要查找的行。如果您定义了索引,它可以使用该索引更快地找到行。

标签: java mysql sql database database-optimization


【解决方案1】:

你可以换一种方式:

用这个 Concats 创建一个 Select

select GROUP_CONCAT(
    CONCAT(" ('",field1,"','",field2,"')")) as vals
from my_table;

结果如下所示:

结果

mysql> select GROUP_CONCAT(
    -> CONCAT(" ('",field1,"','",field2,"')")) as vals
    -> from my_table;
+---------------------------------------------------------------------------------------------------------+
| vals                                                                                                    |
+---------------------------------------------------------------------------------------------------------+
|  ('O1','AC'), ('O1','PT'), ('O2','PT'), ('O3','MI'), ('O3','PT'), ('O4','EG'), ('O4','PT'), ('O5','PT') |
+---------------------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)

mysql>

你可以在插入语句中直接连接这个,你只读取一行,只写和执行一个语句。

您的代码

    String selectStatement = "SELECT GROUP_CONCAT(CONCAT(" ('",field1,"','",field2,"')")) as vals
         FROM dbx.testx where time between ('2016-09-01 00:00:00') and ('2016-09-03 23:59:59');";

    ResultSet resultSetForSelect = st.executeQuery(selectStatement);


    String insertStatement = "INSERT INTO testy(" + "field1," + "field2)" + 
                            + String from result +
                            "ON DUPLICATE KEY UPDATE field1 = VALUES(field1);"; <----field1 is a unique key but not primary


# execute one time

【讨论】:

  • 如果有数千行要插入,字符串会太大,查询也会太大。更不用说如果任何值包含单引号,查询将无效。
  • 但这是主要问题。你有很多插入电话。减少它们。一次获取 16 或 32 个并使用此数量的值对生成第二个准备好的语句
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 2016-08-26
  • 2017-12-12
  • 2011-05-27
相关资源
最近更新 更多