我正在使用Python中的MySQLdb模块与数据库进行交互。我有一种情况,有一个非常大的列表(成千上万的元素),我需要作为行插入表中。
我现在的解决方案是生成一个大的INSERT
语句作为字符串并执行它。
有更聪明的方法吗?
答案 0 :(得分:16)
有一种更聪明的方法。
批量插入的问题是,默认情况下autocommit is enabled会导致每个insert
语句在下一次插入启动之前保存到稳定存储中。
如手册页所述:
默认情况下,MySQL使用autocommit运行 模式已启用。这意味着尽快 当你执行一个语句时 更新(修改)一个表,MySQL 将更新存储在磁盘上以实现它 常驻。要禁用自动提交模式, 使用以下语句:
SET autocommit=0;
禁用后 通过设置自动提交模式 autocommit变量为零,更改 到事务安全表(例如 适用于InnoDB,BDB或NDBCLUSTER的那些) 不会立即成为永久性的。 您必须使用COMMIT来存储您的 更改为磁盘或ROLLBACK忽略 变化。
这是RDBM系统的一个非常常见的特性,它假定数据库完整性至关重要。它确实使批量插入每个插入大约1s而不是1ms。制作一个过大的插入语句的替代方法试图实现这个单一提交,有可能导致SQL解析器重载。
答案 1 :(得分:12)
如果您必须插入大量数据,为什么要尝试将所有数据插入一个insert
? (在执行此大型insert
字符串时,这将不必要地加载内存。如果要插入的数据非常大,这也不是一个很好的解决方案。)
为什么不在db中为每个insert
命令添加一行,并使用for...loop
放置所有行并最终提交所有更改?
con = mysqldb.connect(
host="localhost",
user="user",
passwd="**",
db="db name"
)
cur = con.cursor()
for data in your_data_list:
cur.execute("data you want to insert: %s" %data)
con.commit()
con.close()
(相信我,这真的很快,但如果你的结果变慢,那么这意味着你的autocommit
必须是True
。将其设为False
,msw
说。)
答案 2 :(得分:1)
只要您将其作为单个INSERT进行而不是数千个单独的INSERT,那么这是最好的方法。注意不要超过mysqls的最大数据包大小,并在必要时进行调整。例如,这会将服务器数据包最大值设置为32Mb。您也需要在客户端上执行相同的操作。
mysqld --max_allowed_packet=32M