如何将Python复合键,值字典写入数据库?

我在
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    
点赞