sql >> データベース >  >> RDS >> Mysql

MySQL:ストアドプロシージャ内のテーブルを効率的に入力します

    特にRDBMSではその規模のループを使用しないでください。

    クエリを使用して、テーブルを100万行ですばやく埋めるようにしてください

    INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
    SELECT 1, 'a1', 100, 1, 500000, '2013-06-14 12:40:45'
      FROM
    (
    select a.N + b.N * 10 + c.N * 100 + d.N * 1000 + e.N * 10000 + f.N * 100000 + 1 N
    from (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a
          , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b
          , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) c
          , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) d
          , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) e
          , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) f
    ) t
    

    私の箱(MacBook Pro 16GB RAM、2.6Ghz Intel Core i7)が完了するまでに最大8秒かかりました

    Query OK, 1000000 rows affected (7.63 sec)
    Records: 1000000  Duplicates: 0  Warnings: 0
    

    UPDATE1 これで、プリペアドステートメントを使用するストアドプロシージャのバージョン

    DELIMITER $$
    CREATE PROCEDURE `inputRowsNoRandom`(IN NumRows INT)
    BEGIN
        DECLARE i INT DEFAULT 0;
    
        PREPARE stmt 
           FROM 'INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
                 VALUES(?, ?, ?, ?, ?, ?)';
        SET @v1 = 1, @v2 = 'a1', @v3 = 100, @v4 = 1, @v5 = 500000, @v6 = '2013-06-14 12:40:45';
    
        WHILE i < NumRows DO
            EXECUTE stmt USING @v1, @v2, @v3, @v4, @v5, @v6;
            SET i = i + 1;
        END WHILE;
    
        DEALLOCATE PREPARE stmt;
    END$$
    DELIMITER ;
    

    約3分で完了:

    mysql> CALL inputRowsNoRandom(1000000);
    Query OK, 0 rows affected (2 min 51.57 sec)
    

    8秒と3分の違いを感じてください

    UPDATE2 処理を高速化するために、トランザクションを明示的に使用し、バッチで挿入をコミットできます。したがって、ここではSPの改良版を使用します。

    DELIMITER $$
    CREATE PROCEDURE inputRowsNoRandom1(IN NumRows BIGINT, IN BatchSize INT)
    BEGIN
        DECLARE i INT DEFAULT 0;
    
        PREPARE stmt 
           FROM 'INSERT INTO `entity_versionable` (fk_entity, str1, str2, bool1, double1, date)
                 VALUES(?, ?, ?, ?, ?, ?)';
        SET @v1 = 1, @v2 = 'a1', @v3 = 100, @v4 = 1, @v5 = 500000, @v6 = '2013-06-14 12:40:45';
    
        START TRANSACTION;
        WHILE i < NumRows DO
            EXECUTE stmt USING @v1, @v2, @v3, @v4, @v5, @v6;
            SET i = i + 1;
            IF i % BatchSize = 0 THEN 
                COMMIT;
                START TRANSACTION;
            END IF;
        END WHILE;
        COMMIT;
        DEALLOCATE PREPARE stmt;
    END$$
    DELIMITER ;
    

    バッチサイズが異なる結果:

    mysql> CALL inputRowsNoRandom1(1000000,1000);
    Query OK, 0 rows affected (27.25 sec)
    
    mysql> CALL inputRowsNoRandom1(1000000,10000);
    Query OK, 0 rows affected (26.76 sec)
    
    mysql> CALL inputRowsNoRandom1(1000000,100000);
    Query OK, 0 rows affected (26.43 sec)
    

    自分で違いがわかります 。それでも、クロスジョインの3倍以上悪い。



    1. ローカルのMySQLデータベースに接続するためのPython3.2スクリプト

    2. Mysql Duplicate Rows(2列を使用して重複が検出されました)

    3. MySQLコードをPDOステートメントに変換する方法は?

    4. プログラムによるSQLコードの生成