插入多行时的commit()的最佳实践

时间:2015-06-15 17:53:31

标签: mysql python-3.x transactions database-performance

[情势目的]
我们有一个包含100万行CSV的数据集。这些需要导入到mysql 5.6数据库,带有innodb引擎的表,以下列(匹配csv文件):
第1列:bigint(15)
第2栏:日期时间

要导入此数据,我们可以使用以下python脚本:

#python version: 3.4.3
#mysql connector version: 2.0.4
#Note: this is just a simple example script!

import mysql.connector
import csv

#Set-up db connection
cnx = mysql.connector.connect(user='user', password='secret', database='mydatabase')
cursor = cnx.cursor()

#read/ open csv
reader = csv.reader(open("C:/test.csv", "rt"))

#ignore header
next(reader)

#read CSV and send to mysql
for row in reader:
    id=row[0]
    adate = row[1]
    cursor.execute("""INSERT INTO mytable VALUES ('%s','%s')""" % (id,adate))

#commit the query
cnx.commit()


[问题]
当我将cnx.commit()放在 for 循环中时,概念上发生了什么,如下所示:

for row in reader:
    id=row[0]
    adate = row[1]
    cursor.execute("""INSERT INTO mytable VALUES ('%s','%s')""" % (id,adate))    
    cnx.commit()
  • 如果我理解正确的话,那就是在每次迭代后强制mysql与WRITE之间的区别在于mysql将所有内容存储在其缓存中然后发送commit() - write命令。
  • 这样做有什么性能上的好处?
  • 您是否遵守任何惯例/最佳做法或做法以及原因?

谢谢!

1 个答案:

答案 0 :(得分:1)

你已经展示了两个极端的位置。

一种是在你的megarow插入之后才进行。另一个是在每一行之后提交。

这两个都表现不佳。第一个是糟糕的,因为MySQL创建了一个大事务,然后最终必须提交整个事务。这需要大量的RAM或临时空间。第二个是糟糕的,因为它提交了许多小的交易。

执行此类批量插入的最佳执行方法是每千行左右执行一次。但这比其他方案更难编程。根据我的经验,在每千行左右之后提交的速度比替代方案快几倍,因此值得少量的额外复杂性。

执行此类批量加载的另一种快速(但很脆弱)的方法是使用LOAD DATA INFILE,您可以在此处阅读:https://dev.mysql.com/doc/refman/5.6/en/load-data.html

你的megarow提交有一点点扭曲:MySQL连接可以设置自动提交模式。在这种情况下,你的第一个例子相当于你的第二个例子默认情况下,该模式在python连接器中禁用