10,000件のデータをInsertしてみて1件ずつのCommitと
全件InsertしてからCommitした場合で実行時間を確認してみた。
サンプルコード
# coding: utf-8 try: # import import mysql.connector import string from random import randrange # 接続 connect = mysql.connector.connect(user='root', password='password', host='localhost', database='test', charset='utf8') # カーソル cursor = connect.cursor() # SQL 発行 # cursor.execute('select language_id,name from language',()) for i in range(0, 10000): # Random Charactor Create LENGTH = 20 alphabets = string.digits + string.letters def randstr(n): return ''.join(alphabets[randrange(len(alphabets))] for i in xrange(n)) if __name__ == '__main__': randstr_ins = randstr(LENGTH) insert_stmt = 'insert into language(name) values("%s")' % randstr_ins cursor.execute(insert_stmt) #print insert_stmt #connect.commit() else: print('Finish Creating Data') # フェッチ # # rows = cursor.fetchall() # print(rows) connect.commit() cursor.close() # 切断 connect.close() except Exception as myout: print(myout)
■全てのデータInsertが完了してからCommitした場合
1回目
$ time python mysql_loop.py
Finish Creating Data
real 0m2.017s
user 0m0.000s
sys 0m0.062s
$
2回目
$ time python mysql_loop.py
real 0m1.917s
user 0m0.000s
sys 0m0.015s
$
3回目(100,000件で試してみた)
$ time python mysql_loop.py
Finish Creating Data
real 0m17.972s
user 0m0.000s
sys 0m0.031s
$
randstr_ins = randstr(LENGTH) insert_stmt = 'insert into language(name) values("%s")' % randstr_ins cursor.execute(insert_stmt) #print insert_stmt #connect.commit() else: print('Finish Creating Data') # フェッチ # # rows = cursor.fetchall() # print(rows) connect.commit()
■1件Insert毎にCommitした場合
1回目
$ time python mysql_loop.py
Finish Creating Data
real 0m5.950s
user 0m0.000s
sys 0m0.031s
$
2回目
$ time python mysql_loop.py
Finish Creating Data
real 0m6.006s
user 0m0.000s
sys 0m0.062s
$
3回目(100,000件で試してみた)
$ time python mysql_loop.py
Finish Creating Data
real 0m58.563s
user 0m0.000s
sys 0m0.046s
$
randstr_ins = randstr(LENGTH) insert_stmt = 'insert into language(name) values("%s")' % randstr_ins cursor.execute(insert_stmt) #print insert_stmt connect.commit() else: print('Finish Creating Data') # フェッチ # # rows = cursor.fetchall() # print(rows) # connect.commit()
結果
mysql> select * from language order by language_id desc limit 0,10; +-------------+----------------------+---------------------+ | language_id | name | last_update | +-------------+----------------------+---------------------+ | 80300 | TFEGGvjH8b74uFawV7OS | 2014-08-05 10:11:14 | | 80299 | ZMAF25n87TaIjgT8qJgr | 2014-08-05 10:11:14 | | 80298 | sxV2CjebjaMpmOlQe9Yf | 2014-08-05 10:11:14 | | 80297 | s9c0avx5UumRtcPdtDRu | 2014-08-05 10:11:14 | | 80296 | MH0M5t7jD9F2jGs3jbM4 | 2014-08-05 10:11:14 | | 80295 | Ap4ThCp5RsFHAOrUw0BV | 2014-08-05 10:11:14 | | 80294 | cwLz0e8Vx5L73rzJd6uW | 2014-08-05 10:11:14 | | 80293 | FAfnZReIagqi4mgCnsSV | 2014-08-05 10:11:14 | | 80292 | YfxFjzfJVATB5sEHnkR0 | 2014-08-05 10:11:14 | | 80291 | wENaU30qX4aF51tpDSfY | 2014-08-05 10:11:14 | +-------------+----------------------+---------------------+ 10 rows in set (0.00 sec) mysql> mysql> SELECT @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ mysql>
※ やはりCommitの回数が少ない方が断然早い。
※ InnoDB のデフォルト分離レベルは、REPEATABLE-READなので、
Commitが終わったものが見る事が出来ます。
Selectをバッチ中に確認すると1回毎にCommitしているQueryは、
Selectを実施する毎にその時の最新の状況を確認する事が出来ます。
Reference: 13.5.10.3. InnoDB と TRANSACTION ISOLATION LEVEL
http://dev.mysql.com/doc/refman/5.1/ja/innodb-transaction-isolation.html