批量插入操作太慢

时间:2016-09-24 11:28:21

标签: mysql query-optimization innodb

这是我的' venprices'的结构。表

+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| conid | int(10)     | NO   | PRI | NULL    |       |
| rate  | double      | YES  |     | NULL    |       |
| venid | varchar(50) | NO   | PRI |         |       |
+-------+-------------+------+-----+---------+-------+

JAVA代码:

new Thread(){
            public void run(){
                XSSFWorkbook myWorkBook;
                XSSFSheet mySheet = null;
                Iterator<Row> rowIterator = null;
                String venid = null, errorlog = null;
                int code;
                double rate;
                int rows, maxcount;
                PreparedStatement ps = null;
                Connection con;
                ProgressMonitor pm;
                try {
                    myWorkBook = new XSSFWorkbook(new FileInputStream(new File(jTextField1.getText())));
                    mySheet = myWorkBook.getSheetAt(0);
                    rowIterator = mySheet.iterator();
                    rowIterator.next();
                    venid = jComboBox1.getItemAt(jComboBox1.getSelectedIndex());
                    con = Mycon.getConnection();
                    ps = con.prepareStatement("DELETE FROM venprices WHERE venid = ?");
                    ps.setString(1, venid);
                    ps.executeUpdate();
                    ps.clearBatch();    
                    ps = con.prepareStatement("insert into venprices values (?,?,?)");
                } catch(Exception ioe) {
                    JOptionPane.showMessageDialog(null, ioe.getMessage());
                }
                    rows = 1;maxcount = mySheet.getLastRowNum();
                    // Traversing over each row of XLSX file
                    while (rowIterator.hasNext())
                    {
                        try{
                            Row row = rowIterator.next();
                            Iterator<Cell> cellIterator = row.cellIterator();
                            Cell cell = cellIterator.next();
                            code = (int) cell.getNumericCellValue();
                            cell = cellIterator.next();
                            rate = cell.getNumericCellValue();
                            ps.setInt(1,code);
                            ps.setDouble(2,rate);
                            ps.setString(3, venid);
                            ps.addBatch();
                            rows++;
                        }catch(Exception e){errorlog = errorlog + "\n" +rows+ e.getMessage();}
                    }
                    try{
                        System.gc();
                        ps.executeBatch();
                    }catch(Exception e){e.printStackTrace();}
                    if(errorlog == null)
                        JOptionPane.showMessageDialog(null, "Import Successful. " + rows + " Records Imported.");
                    else
                        JOptionPane.showMessageDialog(null, "Error Log :\n"+errorlog);
            }
        }.start();

用户需要使用Excel文件一次性插入大约50,000条记录。但查询大约需要6-7分钟。 任何人都可以帮我减少插入操作时间或告诉我插入查询中的一些调整? 在此先感谢!

编辑1: 如所要求的,这是show create table venprices

的结果
mysql> show create table venprices;
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                          |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| venprices | CREATE TABLE `venprices` (
  `conid` int(10) NOT NULL,
  `rate` double DEFAULT NULL,
  `venid` varchar(50) NOT NULL DEFAULT '',
  PRIMARY KEY (`conid`,`venid`),
  KEY `vepr` (`conid`,`rate`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

1 个答案:

答案 0 :(得分:1)

我不知道Java语法,但在代码的开头添加了一个MySQL START TRANSACTIONBEGIN)。并将COMMIT添加到最后。

为什么?

在6-7分钟内插入50K行气味非常类似于在自己的事务中插入每一行(la autocommit=ON)。由于磁盘上的所有事务活动,这很慢。

通过将50K事务转换为1个事务,您将获得更少的I / O,因此它将运行得更快。

其次......通过将50K 1行INSERTs转换为50行1000 INSERTs,您可以获得另外10倍的加速。这是因为避免了客户端和服务器之间的大部分往返时间以及大部分解析时间。 (同样,我不知道Java是否有一个特殊的类来促进这样做;它可能。)

这两项更改可能与Drew的LOAD_DATA INFILE方法竞争。