遍历大列表时,Python运行速度很慢
问题描述:
我当前正在使用pyodbc从数据库中选择一大列行。然后将结果复制到一个大的列表中,然后我尝试遍历列表。在放弃Python之前,尝试用C#创建它之前,我想知道是否有某件事情我做错了。遍历大列表时,Python运行速度很慢
clientItems.execute("Select ids from largetable where year =?", year);
allIDRows = clientItemsCursor.fetchall() #takes maybe 8 seconds.
for clientItemrow in allIDRows:
aID = str(clientItemRow[0])
# Do something with str -- Removed because I was trying to determine what was slow
count = count+1
一些详细信息:
- for循环正在运行以每秒约5圈,这似乎出奇的慢我。
- 所选的总行数是〜489,000。
- 它运行的机器有很多RAM和CPU。它似乎只运行一个或两个内核,RAM为1.72GB的4GB。
任何人都可以告诉我什么是错的?脚本运行缓慢吗?
感谢
答
这不应该是用Python自身名单慢 - 但也许ODBC的驱动程序返回了试图成为一个聪明的“懒”对象,但只是变得缓慢。尝试只是在做
allIDRows = list(clientItemsCursor.fetchall())
在你的代码和后进一步基准。
答
,因为你第一次加载所有结果在内存中,在一个列表进行迭代这可能是缓慢的。尝试迭代游标。
而且不,脚本不应该是那慢。
clientItemsCursor.execute("Select ids from largetable where year =?", year);
for clientItemrow in clientItemsCursor:
aID = str(clientItemrow[0])
count = count + 1
答
这里需要更多的调查
(如果你开始将在中间的东西,但只是迭代的大名单应该是快速Python列表可以很慢)...考虑下面的脚本:
bigList = range(500000)
doSomething = ""
arrayList = [[x] for x in bigList] # takes a few seconds
for x in arrayList:
doSomething += str(x[0])
count+=1
这与您的脚本非常相似,减去数据库内容,并且需要几秒钟才能在我的非常快的机器上运行。
答
当你直接连接到你的数据库(我的意思是你得到一个SQL提示符)时,多少个secods运行这个查询?
当查询结束后,你会得到类似这样的消息:
NNNNN rows in set (0.01 sec)
所以,如果时间是如此之大,和您的查询速度慢作为“原生”,可能是你必须在创建索引那张桌子。
答
因为你是
- 获取所有的结果
- 分配内存和分配的值是内存中创建列表allIDRows
- 遍历该列表和计数这是缓慢的。
如果execute返回一个游标,那么使用游标是有好处的,并且在你回收内容并在mem分配上节省时间时开始计数。
clientItemsCursor.execute("Select ids from largetable where year =?", year);
for clientItemrow in clientItemsCursor:
count +=1
其他提示:
- 同比创建索引
- 使用“选择... COUNT(*),以获得该年度的计数”这很可能会在优化D b。
- 如果不需要,删除aID行,即使未使用该行,也会将该行的第一项转换为字符串。
'clientItemRow [0]'真的很大吗? 489,000行是低的,但5行/秒的速度慢得可笑。另外,如果我错了,有人可以纠正我,但我敢肯定你的代码只能在一个内核上运行,但仍应该比每秒5次更快。此外,您可以使用内置的cProfile来查看您打到瓶颈的位置。 – prelic 2012-02-22 20:09:03
至于CPU的使用情况 - 如果你用取得的结果做了一些奇特的事情,你可以通过使用Python的多处理模块来获得更多的CPU核心 - 但是我们可以首先理解这种交互方式。 – jsbueno 2012-02-22 20:09:20
'type(allIDRows)'返回什么? – tMC 2012-02-22 20:10:09