2

我正在尝试将 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 而不是 oursql,大约需要 2 秒。为什么会有这么大的差异?这应该在oursql中以其他方式完成吗,我们的oursql只是很慢?如果有更好的方法用我们的sql插入这些数据,如果你能告诉我,我将不胜感激。

谢谢你。

4

3 回答 3

7

不同之处在于 MySQLdb 对您的查询进行了一些黑客攻击,而我们的 SQL 则没有......

采取这个:

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]])

在我们的sql中,它被翻译成类似这样的伪代码:

stmt = prepare("INSERT INTO sometable VALUES (?, ?, ?)")
for params in [[1,2,3],[4,5,6],[7,8,9]]:
    stmt.execute(*params)

因此,如果您想模拟 mysqldb 正在做什么,但要从准备好的语句和 oursql 的其他优点中受益,您需要这样做:

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))

我敢打赌,当你这样做时,oursql 会更快 :-)

另外,如果您认为它丑陋,那您是对的。但是请记住 MySQL db 在内部做了一些更丑陋的事情 - 它使用正则表达式来解析您的 INSERT 语句并中断参数化部分,然后执行我建议您为 oursql 做的事情。

于 2014-06-19T22:07:39.293 回答
1

我会说检查是否oursql支持bulk insertsql 命令以提高性能。

于 2012-06-16T05:50:32.100 回答
0

Oursql 确实支持bulk insert语句。我已经使用 sqlalchemy 包装器编写了这样做的代码。

对于纯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' ;""")

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

于 2012-08-06T18:03:37.830 回答