oursql在插入数据时极其缓慢

时间:2012-06-15 15:05:59

标签: python mysql database oursql

我试图将一些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插入这些数据,如果你能告诉我,我将不胜感激。

谢谢。

3 个答案:

答案 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' ;""")

请注意,行的顺序必须与数据库中的列的顺序相同。