6

テーブル

+ ----------- + -------------- + ------ + ----- + --------- ---------- + ---------------- +
| フィールド| タイプ| ヌル| キー| デフォルト| エクストラ|
+ ----------- + -------------- + ------ + ----- + --------- ---------- + ---------------- +
| id | int(11)| いいえ| PRI | NULL | auto_increment |
| 名前| varchar(32)| いいえ| | NULL | |
| pid | varchar(32)| いいえ| | NULL | |
+ ----------- + -------------- + ------ + ----- + --------- ---------- + ---------------- +

手順:テスト

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秒かかります)。

Javaコード:

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テキストの最初の位置パラメーターのバインドは表示されず、2番目と3番目のパラメーターのみが表示されます。(おそらく間違っている)次のように仮定します。 JDBCは、バインドされていないパラメーターに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 に答える