【问题标题】:Best practices of commit() when inserting many rows插入多行时 commit() 的最佳实践
【发布时间】:2015-08-31 08:09:33
【问题描述】:

[情境-目标]
我们有一个 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 写入与 mysql 将所有内容存储在其缓存中然后发送 commit() - 写入命令之间的区别。
  • 这样做有哪些性能提升/缺点?
  • 您是否遵守任何约定/最佳做法或做法?为什么?

谢谢!

【问题讨论】:

  • 有点跑题了:你考虑过LOAD DATA INFILE的用法吗?另请阅读transactions
  • 欢迎来到 Stack Overflow,感谢您提出一个好问题!

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


【解决方案1】:

你展示了两个极端的立场。

一种是仅在您的大量插入之后提交。另一种是在每一行之后提交。

这两者的性能都很差。第一个很糟糕,因为 MySQL 创建了一个大事务,然后最后必须提交整个事务。这需要大量 RAM 或临时空间。第二个很糟糕,因为它提交了许多小事务。

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

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

您的 megarow 提交有一个小变化:MySQL 连接可以设置自动提交模式。在这种情况下,您的第一个示例等同于您的第二个示例。默认情况下,该模式在 python 连接器中为 disabled

【讨论】:

  • 感谢您提供信息丰富的回复。我只是想问你是否做过或知道任何仔细观察“每 1K 左右”的测试。并不是说我不相信你,而是我很好奇“甜蜜的数字”或“最佳实践”是什么。我知道有很多变量在起作用,这使得这个问题很难回答,但仍然:)
  • 顺序 I/O ~ 128 kb 每次读/写,随机 I/O ~ 4kb / 每次读/写。如果您有 300 IOPS 可用并且您正在随机写入(机械驱动器),那么就驱动器将写入的内容而言,您的最佳位置是适合 4kb * 300 的东西。这通常更难计算,但测量起来非常简单——您必须自己找出这个数字,因为我们无法猜测每笔交易可能有多少数据,而您可以通过暴力导入找到。就个人而言,我在寻找性能时每次提交都会写 1000 行,但你的里程可能会有所不同。
  • 我在做那个项目时并没有进行性能研究,而是在争先恐后地加载一些数据。我尝试每次提交 200 行,每次提交 1000 行。它们每分钟的聚合行数非常接近。 LOAD DATA INFILE 比任何一个都快。
  • 1000 个批次可能是您可以获得的最快速度的 1% 以内。 100 或 10000 批可能只会稍微慢一些。还记得解析几何、微积分或数值分析中的“抛物线”吗?并找到最小点?有点像。
猜你喜欢
  • 2010-10-17
  • 2018-01-30
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多