我有一个python中的复合键字典,如下所示:
key value
("a","b") (1,2,3)
("c","d") (4,5,6)
("e","f") (7,8,9)
键和值都是元组我想以最有效的方式将其保存到sqlite数据库表中,如下所示:
row col1 col2 col3 col4 col5
1 "a" "b" 1 2 3
2 "c" "d" 4 5 6
3 "e" "f" 7 8 9
为此,我尝试逐行连接键和值,然后使用INSERT将此结构传递给executemany()这很有效,但速度非常慢:
writedata = []
for i in range(0, len(mydict.keys())):
writedata.append(mydict.keys()[i] + mydict.values()[i])
sql = "INSERT INTO mytable VALUES (?,?,?,?,?)"
mydbcursor.executemany(sql, writedata)
我有一个非常大的数据集,所以理想情况下我甚至不想创建上面的writedata这样的二级结构。
我在这里尝试了很多解决方案(列表理解、列表+、列表扩展、生成器等等),但是我没有找到处理这个案例的正确方法。
任何帮助或链接将不胜感激!谢谢!
最佳答案
Cursor.executemany()
也适用于迭代器:
sqlite3模块还允许使用迭代器生成参数
而不是一个序列。
因此,可以将生成器传递给它,而不是先创建中间列表:
mydbcursor.executemany(sql, (k + v for k, v in mydict.iteritems()))
在Python3中,如果在内存中创建列表,则可以使用返回项目视图的
.iteritems()
。如果将
.items()
与for
一起使用,我们可以从代码中完全删除itertools.starmap
循环,从而加快速度:mydbcursor.executemany(sql, starmap(add, dct.iteritems())
时间比较表明,使用上述迭代器所需的时间更少:
In [34]: from operator import add
In [35]: from itertools import starmap
In [36]: dct = {(i, 'a', 'b'): (1, 2, 3) for i in xrange(10**6)}
In [37]: %timeit for _ in (k+v for k, v in dct.iteritems()): pass
1 loops, best of 3: 290 ms per loop
In [38]: %timeit for _ in starmap(add, dct.iteritems()): pass
1 loops, best of 3: 256 ms per loop
In [39]: %timeit list(starmap(add, dct.iteritems()))
1 loops, best of 3: 335 ms per loop
In [40]: %timeit list(k+v for k, v in dct.iteritems())
1 loops, best of 3: 415 ms per loop