6

桌子

+-----------+-------------+------+-----+--------- ----------+----------------+
| 领域 | 类型 | 空 | 钥匙 | 默认 | 额外 |
+-----------+-------------+------+-----+--------- ----------+----------------+
| 编号 | 整数(11) | 否 | 优先级 | 空 | 自动增量 |
| 姓名 | varchar(32) | 否 | | 空 | |
| 进程号 | varchar(32) | 否 | | 空 | |
+-----------+-------------+------+-----+--------- ----------+----------------+

程序:测试

begin
  set @i=0;
  while @i<200 do
    insert into test.table_test
      (name, pid) values ('1', '1');
    set @i=@i+1;
  end while;
end

跑:

mysql> call test();
Query OK, 0 rows affected (17.24 sec)

但是当我用 jdbc 插入数据时,插入 10^5 行只需要大约 9 秒(如果我使用批量插入,插入 10^5 行只需要大约 2.4 秒)。

爪哇代码:

static String mySqlUrl="jdbc:mysql://127.0.0.1:3306/test?rewriteBatchedStatements=true";

static String sql = "insert into bael_test(name, pid) values(?, ?)"; 

public static void test_mysql_batch(int point){  
    Connection conn=getConn("mysql");  
    clear(conn);
    try {        
        PreparedStatement prest = conn.prepareStatement(sql);        
        long a=System.currentTimeMillis();  
        for(int x = 1; x <= 100000; x++){            
            prest.setString(1, "name");
            prest.setString(2, "pid");
            prest.addBatch();    
            if(x%point==0){
                    prest.executeBatch();      
                    conn.commit();
            }
        }        
        long b=System.currentTimeMillis();  
        print("MySql batch insert 10^5 rows",a,b,point);
    } catch (Exception ex) {  
        ex.printStackTrace();  
    }finally{  
        close(conn);    
    }  
} 

那么为什么 MySQL 插入比 JDBC 慢呢?

4

2 回答 2

2

您的 Java 代码使用准备好的语句,而您的 MySQL 代码没有。

换句话说,如果您的查询语法正确,您的过程必须在循环的每个步骤中检查,以及在磁盘上定位表,而准备好的语句仅执行此操作,并且只会在正确的位置插入值无需进一步处理。

如果要比较,可以使用PREPARE-> http://dev.mysql.com/doc/refman/5.0/en/sql-syntax-prepared-statements.html

只是从内存中写出来,所以它可能是错误的:

PREPARE stmt1 FROM 'INSERT INTO test.table_test (name,pid) values(?,?)';
while @i<200 do
    EXECUTE stmt1 USING @i, @i;;
    set @i=@i+1;
  end while;
DEALLOCATE PREPARE stmt1;
于 2012-07-13T17:01:52.440 回答
1

JDBC 代码正在执行扩展插入。

(我们在这里没有看到实际的 SQL 语句,也没有看到 SQL 文本中第一个位置参数的绑定,只有第二个和第三个参数。我将做一个假设(可能是错误的) JDBC 为 unbound 参数提供 NULL 值。)

因此,从 JDBC 驱动程序发送到 MySQL 的实际 SQL 语句是以下形式:

INSERT INTO test.table_test (id,name, pid) VALUES (NULL,'name','pid')
,(NULL,'name','pid')
,(NULL,'name','pid')
,(NULL,'name','pid')
,...

但是,在您的 MySQL 过程中,您正在执行单独的语句:

INSERT INTO test.table_test (id,name,pid) VALUES (NULL,'name','pid');
INSERT INTO test.table_test (id,name,pid) VALUES (NULL,'name','pid');
INSERT INTO test.table_test (id,name,pid) VALUES (NULL,'name','pid');
INSERT INTO test.table_test (id,name,pid) VALUES (NULL,'name','pid');

扩展的插入形式将比单独的插入语句更有效。(MySQL 为每个语句执行做了很多繁重的工作。)

要从 MySQL 过程中获得更好的性能,您需要执行以下操作:

BEGIN
  SET @sqltext= 'insert into test.table_test (name,pid) values (''1'',''1'')'; 
  SET @i=1;
  WHILE @i<200 DO
    SET @sqltext = CONCAT(@sqltext,',(''1'', ''1'')');
    SET @i=@i+1;
  END WHILE;
  PREPARE stmt FROM @sqltext;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END

为了从 JDBC 中获得同样的性能下降,您需要执行单独的 INSERT 语句。

这是您看到的巨大性能差异的最大贡献者。

这并不是说这是唯一的区别,但这解释了您在执行程序时看到的大部分 17 秒经过的时间。使用单个扩展插入的过程可能比运行 200 个单独插入快 100 倍。

您仍然存在性能差异,但至少与苹果相比,您更接近于比较苹果。

于 2012-07-13T19:10:21.470 回答