我在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这样的二级结构.
我已尝试在SO上遵循许多解决方案(列表理解,列表,列表扩展,生成器……)但我没有找到正确的方法来处理这种情况.
任何帮助或链接将不胜感激!谢谢!
解决方法:
Cursor.executemany()
也适用于迭代器:
The sqlite3 module also allows using an iterator yielding parameters
instead of a sequence.
因此,您可以将生成器传递给它,而不是先创建中间列表:
mydbcursor.executemany(sql, (k + v for k, v in mydict.iteritems()))
在Python3 .iteritems()不起作用,你可以使用.items(),如果在内存中创建一个列表,它将返回项目的视图.
如果我们通过使用带有operator.add的itertools.starmap从代码中完全删除for循环,我们可以加快速度:
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