我在python中有一个函数,在我的表中得分。我想算术地计算所有行的分数(例如,计算分数的总和,平均值等)。
def compute_score(row):
# some complicated python code that would be painful to convert into SQL-equivalent
return score
显而易见的第一种方法是简单地读入所有数据
import psycopg2
def sum_scores(dbname, tablename):
conn = psycopg2.connect(dbname)
cur = conn.cursor()
cur.execute('SELECT * FROM ?', tablename)
rows = cur.fetchall()
sum = 0
for row in rows:
sum += score(row)
conn.close()
return sum
我希望能够处理数据库可以容纳的数据。这可能会更大,以适应Python的内存,所以fetchall()
在我看来就好像在这种情况下无法正常运行。
我正在考虑3种方法,所有这些方法都是为了一次处理几条记录:
使用fetchone()
def sum_scores(dbname, tablename):
...
sum = 0
for row_num in cur.rowcount:
row = cur.fetchone()
sum += score(row)
...
return sum
使用fetchmany(n)
def sum_scores(dbname, tablename):
...
batch_size = 1e3 # tunable
sum = 0
batch = cur.fetchmany(batch_size)
while batch:
for row in batch:
sum += score(row)
batch = cur.fetchmany(batch_size)
...
return sum
依赖游标的迭代器
def sum_scores(dbname, tablename):
...
sum = 0
for row in cur:
sum += score(row)
...
return sum
我的想法是否正确,因为我提出的3个解决方案一次只能提取可管理大小的数据块?或者他们遇到与fetchall
相同的问题?
对于LARGE数据集,3个提出的解决方案中哪一个可以正常工作(即计算正确的分数组合而不是崩溃)?
游标的迭代器(建议的解决方案#3)如何实际将数据输入Python的内存?一个接一个,分批,或一次一个?
答案 0 :(得分:4)
所有3个解决方案都可以使用,并且只将结果的一部分带入内存。
如果将名称传递给光标,则通过游标进行迭代,建议的解决方案#3将与建议的解决方案#2相同。迭代光标将获取 itersize 记录(默认为2000)。
解决方案#2和#3将比#1快得多,因为连接开销要少得多。