我有一个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

09-04 09:28
查看更多