性能插入声明?

时间:2018-02-22 11:40:16

标签: java mysql jdbc apache-poi query-performance

我有从excel表读取的应用程序,超过25000条记录的记录数。我计算了将记录插入数据库的时间 15分钟,目前正在使用MySQL,以后可能会改为db2。

我将所有语句直接插入MySQL,所用时间为14分钟。

这是正常的吗?有没有办法提高性能?或代码增强?

/**
     * insert records excel sheeet in tables 
     * @param dbConnection
     * @throws Exception
     */
    void insertRecords(Connection dbConnection,Sheet sheet,int sizeColumns ,String tableName) throws Exception {

        PreparedStatement preparedStatement = null;

        try {


            Sheet datatypeSheet =sheet;
            Iterator<Row> iterator = datatypeSheet.iterator();
            StringBuilder sbInsert = new StringBuilder( 1024 );

            //skip first row 
            iterator.next();

            //iterator for rows excel sheet
            while (iterator.hasNext()) {

                sbInsert.setLength(0);

                Row currentRow = iterator.next();

                sbInsert.append("insert into "+tableName.trim().replaceAll(" ","_")+" values(");

                int currentCellLenght=0;


                //iterator for cell rows
                for(int cn=0; cn<sizeColumns; cn++) {


                    Cell currentCell = currentRow.getCell(cn, MissingCellPolicy.CREATE_NULL_AS_BLANK);
                    currentCell.setCellType(Cell.CELL_TYPE_STRING);
                    String cellValue;

                    cellValue=currentCell.getStringCellValue();

                    sbInsert.append("'"+cellValue.replaceAll("\'", "")+"'");


                    currentCellLenght++;


                    if(currentCellLenght==sizeColumns) {
                        break;

                    }

                    //add insert rows 
                    if(currentCellLenght!=sizeColumns) {
                        sbInsert.append(",");
                    }


                }

                sbInsert.append(")");

                preparedStatement = dbConnection.prepareStatement(sbInsert.toString());
                preparedStatement.execute();


            }

        } catch (EncryptedDocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());

        }finally {
            if (preparedStatement != null) {
                preparedStatement.close();
            }
            dbConnection.close();

        }

    }

2 个答案:

答案 0 :(得分:2)

当你用一系列插入语句天真地命中MySQL中的InnoDB表时,它会自动提交每个语句,然后才能获取下一个语句。这需要很多额外的时间。

您可以通过在多行块中进行插入来解决此问题。

一种方法是使用事务来填充插入块。在操作开始时,执行Connection.setAutoCommit(false);。然后,每隔几百行Connection.commit();。处理完所有行后,不要忘记执行最后Connection.commit();。而且,如果您继续使用相同的连接进行其他操作,请执行Connection.setAutoCommit(true);

另一种方法是发出多行插入。他们看起来像这样。

INSERT INTO table VALUES
   (val1, val2, val3, val4),
   (val5, val6, val7, val8),
    ...
   (val9, vala, valb, valc);

括号中的每组值都是一行。您可以在每个插入语句中放入十行甚至五十行。这本身就是一种分块插入的方法,因为每个多行插入仅使用一个事务。

另一种加快速度的方法(可能是一种低级方式)。使用MyISAM表而不是InnoDB。 MyISAM没有事务,因此它没有开销。但是当你在生产中使用表格时,交易很好。

Chunking对像您这样的批量插入性能问题产生了差异。

答案 1 :(得分:0)

第一次使用JAVA第二次运行总是因为负载和其他初始化而更快。保持良好的工作。

代码审核。

你两次评估同样的事情 你可以在这里用一个else语句来节省一些时间。

IRL您对sizeColumns的迭代无需检查它。第一个if语句不需要。

IRL第一列然后开始迭代现在只需在每个值之前加上一个逗号并在结尾处关闭语句。不再需要第二个if语句。

if(currentCellLenght==sizeColumns) {
                        break;

                  }

                    //add insert rows 
                    if(currentCellLenght!=sizeColumns) {
                        sbInsert.append(",");
                    }