我编写了一些代码,只需从数据库中读取数据并将结果保存到python中的集合中
我第一次写的时候是把项目存储在字典里,但是后来我意识到索引只是增量的,所以我把它改成了list
。你知道吗
然而在那之后,程序的速度急剧下降。我最初认为MySQL数据库有问题,但后来我把集合改成了dict
,它又恢复了正常。你知道吗
代码是这样的:
cursor = db.cursor(pymysql.cursors.SSDictCursor)
cursor.execute('SELECT * FROM db')
coll = [] # or coll = {}
for i in cursor:
coll.append(i) # or coll[len(coll)] = i
我分别比较了coll.append()
和coll[len(coll)] = i
,这些线本身似乎没有太大的差别(append比较慢,但不足以导致戏剧性的减速,这在不同的数量级上)
我认为排序可能会引起一些问题,当我使用OrderedDict
时,速度似乎没有受到影响。你知道吗
我想知道它是否可以基于列表和字典是如何实现的(可能列表必须保存在连续内存中,因此需要频繁地重新分配内存,而字典不必是连续的),但我想知道为什么会发生这种情况
编辑:
以下是我正在运行的实际代码,以防简化代码缺少相关内容:
with closing(cdr_db.cursor(pymysql.cursors.SSDictCursor)) as cdr_cursor:
cdr_cursor.execute(query.format(TABLE_NAME))
nID_to_num = {} # []
num_to_nID = {}
g = snap.TNGraph.New()
for call in cdr_cursor:
from_num = call['from_num']
to_num = call['to_num']
if from_num == 0 or to_num == 0:
continue
if from_num not in num_to_nID:
curr_index = len(nID_to_num)
g.AddNode(curr_index)
num_to_nID[from_num] = curr_index
nID_to_num[curr_index] = from_num # nID_to_num.append(from_num)
if to_num not in num_to_nID:
curr_index = len(nID_to_num)
g.AddNode(curr_index)
num_to_nID[to_num] = curr_index
nID_to_num[curr_index] = to_num # nID_to_num.append(to_num)
g.AddEdge(num_to_nID[from_num], num_to_nID[to_num])
这是在Windows7的Python2.7 64位中运行的。你知道吗
在新代码发布后更新,并且在Mark和Antti之间来回更新:
我相信您的原始测试用例没有显示问题的原因是,在您的原始测试用例中,您只显示了对dict用例使用
len()
,在您的完整示例中,您总是使用len()
。你知道吗在进一步研究计时之后,我发现如果我修改下面的列表示例以更接近您的完整示例,例如
coll.append(len(coll))
,因为您在这两种情况下都在计算len(),那么dict的情况会更快。您最初的小示例错误地将len()的成本归因于dict版本,即使两个版本都调用len()。你知道吗然而,(假设您是在函数中执行这段代码,而不是在脚本级别执行,因为所有的查找都是昂贵的),我发现通过在循环外预定义
a = coll.append
并使用它,我可以恢复时间并再次比dicts更快地生成列表。你知道吗如果这是您正在看到的问题,并且时间紧迫,那么您可能希望将其他一些查找移到循环之外,例如
len
和g.AddNode
的查找。你知道吗**以下为原始答案**
在这个用例中,我无法验证您关于dict比list快的说法,所以您可能更改了其他内容。您没有指定版本,所以我主要使用Python2,但使用3来确定它在某些情况下具有可比性。代码如下:
以下是一些结果:
对于更大的容器,清单是一个明显的赢家5倍快与10e6项目。dicts唯一领先的地方是python2.7,每个容器只有一个条目,而且数量很少。你知道吗
这是一个32位的ubuntu14.04系统。你知道吗
相关问题 更多 >
编程相关推荐