我试图将一些python脚本生成的数据存储在MySQL数据库中。基本上我使用的是命令:
con = oursql.connect(user="user", host="host", passwd="passwd",
db="testdb")
c = con.cursor()
c.executemany(insertsimoutput, zippedsimoutput)
con.commit()
c.close()
其中,
insertsimoutput = '''insert into simoutput
(repnum,
timepd,
...) values (?, ?, ...?)'''
插入约30,000行,大约有15列。以上大约需要7分钟。如果我使用MySQLdb而不是我们的MySQL,大约需要2秒钟。为何如此巨大的差异?这应该是在myql中以其他方式完成的,我们的自己的mysql只是很慢吗?如果有更好的方法可以用oursql插入这些数据,如果你能告诉我,我将不胜感激。
谢谢。
答案 0 :(得分:7)
不同之处在于MySQLdb对你的查询做了一些hackery,而我们的mysql没有......
考虑到这一点:
cursor.executemany("INSERT INTO sometable VALUES (%s, %s, %s)",
[[1,2,3],[4,5,6],[7,8,9]])
MySQLdb在运行之前对其进行翻译:
cursor.execute("INSERT INTO sometable VALUES (1,2,3),(4,5,6),(7,8,9)")
但如果你这样做:
cursor.executemany("INSERT INTO sometable VALUES (?, ?, ?)",
[[1,2,3],[4,5,6],[7,8,9]])
在oursql中,它被翻译成类似伪代码的东西:
stmt = prepare("INSERT INTO sometable VALUES (?, ?, ?)")
for params in [[1,2,3],[4,5,6],[7,8,9]]:
stmt.execute(*params)
因此,如果你想模仿mysqldb正在做的事情,但是从预备语句和selfql的其他优点中受益,你需要这样做:
from itertools import chain
data = [[1,2,3],[4,5,6],[7,8,9]]
one_val = "({})".format(','.join("?" for i in data[0]))
vals_clause = ','.join(one_val for i in data)
cursor.execute("INSERT INTO sometable VALUES {}".format(vals_clause),
chain.from_iterable(data))
我敢打赌,当你这样做时,我们的版本会更快: - )
另外,如果你觉得它丑陋,那你就是对的。但是请记住,MySQL db在内部做了一些更糟糕的事情 - 它使用正则表达式来解析你的INSERT语句并中断参数化部分,然后执行我建议你为我们做的事情。
答案 1 :(得分:1)
我想说检查oursql
是否支持bulk insert
sql命令以提高性能。
答案 2 :(得分:0)
Oursql支持bulk insert
语句。我已经使用sqlalchemy包装器编写了代码。
对于pure oursql,这样的事情应该没问题:
with open('tmp.csv', 'wb') as tmp:
for item in zippedsimoutput:
tmp.write("{0}\n".format(item))
c.execute("""LOAD DATA LOCAL INFILE 'tmp.csv' INTO TABLE flags FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\r\n' ;""")
请注意,行的顺序必须与数据库中的列的顺序相同。