【发布时间】:2015-10-03 11:17:11
【问题描述】:
我有一个 Python 程序,它使用Pytables 并以这种简单的方式查询一个表:
def get_element(table, somevar):
rows = table.where("colname == somevar")
row = next(rows, None)
if row:
return elem_from_row(row)
为了减少查询时间,我决定尝试使用table.copy(sortby='colname') 对表进行排序。这确实提高了查询时间(在where 中花费的时间),但它在next() 内置函数中花费的时间增加了几个数量级!可能是什么原因?
仅当表中有另一列时才会出现这种减速,并且减速随着该另一列的元素大小而增加。
为了帮助我理解问题并确保这与我的程序中的其他内容无关,我制作了这个最小的工作示例来重现问题:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import tables
import time
import sys
def create_set(sort, withdata):
#Table description with or without data
tabledesc = {
'id': tables.UIntCol()
}
if withdata:
tabledesc['data'] = tables.Float32Col(2000)
#Create table with CSI'ed id
fp = tables.open_file('tmp.h5', mode='w')
table = fp.create_table('/', 'myset', tabledesc)
table.cols.id.create_csindex()
#Fill the table with sorted ids
row = table.row
for i in xrange(500):
row['id'] = i
row.append()
#Force a sort if asked for
if sort:
newtable = table.copy(newname='sortedset', sortby='id')
table.remove()
newtable.rename('myset')
fp.flush()
return fp
def get_element(table, i):
#By construction, i always exists in the table
rows = table.where('id == i')
row = next(rows, None)
if row:
return {'id': row['id']}
return None
sort = sys.argv[1] == 'sort'
withdata = sys.argv[2] == 'withdata'
fp = create_set(sort, withdata)
start_time = time.time()
table = fp.root.myset
for i in xrange(500):
get_element(table, i)
print("Queried the set in %.3fs" % (time.time() - start_time))
fp.close()
这里是一些显示数字的控制台输出:
$ ./timedset.py nosort nodata Queried the set in 0.718s $ ./timedset.py sort nodata Queried the set in 0.003s $ ./timedset.py nosort withdata Queried the set in 0.597s $ ./timedset.py sort withdata Queried the set in 5.846s
一些注意事项:
- 实际上在所有情况下都对行进行了排序,因此它似乎与知道排序的表相关联,而不仅仅是正在排序的数据。
- 如果不是创建文件,而是从磁盘读取文件,结果相同。
- 仅当数据列存在时才会出现此问题,即使我从未写入或读取它。我注意到当列的大小(浮点数)增加时,时间差“分阶段”增加。减速必须与内部数据移动或 I/O 相关联:
- 如果我不使用
next函数,而是使用for row in rows并相信只有一个结果,那么仍然会出现减速。
通过某种 id(排序或未排序)访问表中的元素听起来像是一个基本功能,我一定错过了使用 pytables 执行此操作的典型方法。它是什么? 为什么会出现如此可怕的放缓?这是我应该报告的错误吗?
【问题讨论】:
标签: python optimization iterator pytables