插入性能调整

时间:2016-05-31 12:42:58

标签: java sql sql-server oracle

目前,我们正在从一个database中选择数据并将其插入备份数据库(SQL SERVER)。

此数据在一个选择中始终包含超过15K的记录。   我们使用Enumeration来迭代所选的数据。

我们正在使用JDBC PreparedStatement将数据插入:

    Enumeration values = ht.elements(); -- ht is HashTable containing selected data.
        while(values.hasMoreElements())
        {
                pstmt = conn.prepareStatement("insert query");
                            pstmt.executeUpdate();
        }

我不确定这是否是更快插入的正确或有效方法。

对于插入10k行,需要大约30分钟或更长时间。 是否有任何有效的方法使其快速? 注意:不使用表格中的任何索引。

3 个答案:

答案 0 :(得分:1)

您可以在一个sql命令中插入所有值:

INSERT INTO Table1 ( Column1, Column2 ) VALUES
( V1, V2 ), ( V3, V4 ), .......

您也可以按500个记录的批量插入值,例如,如果查询变得非常大。远程(使用连接)在每个语句的行上插入是没有效率的。另一种解决方案是使用存储过程进行插入。您只需将值作为参数传递给它。

以下是使用上述INSERT命令执行此操作的方法:

 Enumeration values = ht.elements(); -- ht is HashTable containing selected data.
 int i=0;
 String sql="";

    while(values.hasMoreElements())
    {
            sql+="(" + values + ")"; //better use StringBuffer here
            i++;
            if(i % 500 == 0) {
                pstmt = conn.prepareStatement("insert query "+sql);
                pstmt.executeUpdate();
                sql="";
            }
            else
                sql += " , ";
    }

答案 1 :(得分:1)

使用批量插入,但在几次委托之后提交,不要尝试一次发送所有10K。尝试调查以获得最佳尺寸,这是对内存与网络旅行的折衷。

Connection connection = new getConnection();
Statement statement = connection.createStatement();
int i = 0;

for (String query : queries) {
    statement.addBatch("insert query");
    if ((i++ % 500) == 0) {
         // Do an execute now and again, don't send too many at once
        statement.executeBatch(); 
    }
}

statement.executeBatch();
statement.close();
connection.close();

另外,从您的代码中我不确定您在做什么,但使用参数化查询而不是将10K插入语句作为文本发送。类似的东西:

String q= "INSERT INTO data_table (id) values (?)";
Connection connection = new getConnection();
PreparedStatement ps = connection.prepareStatement(q);

for (Data d: data) {     
    ps.setString(1, d.getId());
    ps.addBatch();
}

ps.executeBatch();
ps.close();
connection.close(); 

答案 2 :(得分:1)

您可以做的最简单的事情是对所有INSERT语句使用单个事务:

Enumeration values = ht.elements(); -- ht is HashTable containing selected data.

    conn.CallMethodForBeginTx();

    while(values.hasMoreElements())
    {
            pstmt = conn.prepareStatement("insert query");
                        pstmt.executeUpdate();
    }

    conn.CallMethodForCommitTx();

并且也不要忘记管理sql异常(conn.CallMethodForRollbackTx();

描述了这两种方法在性能方面的差异here

如果性能仍然存在问题请再现。