在Python中处理大型数据库表的每一行

Ped*_*ori 6 python psycopg2 bigdata

上下文

我在python中有一个函数,在我的表中得分.我想算术地计算所有行的分数(例如,计算分数的总和,平均值等).

def compute_score(row):
  # some complicated python code that would be painful to convert into SQL-equivalent
  return score
Run Code Online (Sandbox Code Playgroud)

显而易见的第一种方法是简单地读入所有数据

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
Run Code Online (Sandbox Code Playgroud)

问题

我希望能够处理尽可能多的数据,因为我的数据库可以容纳.这可能会更大,以适应Python的内存,所以fetchall()在我看来,在这种情况下它将无法正常运行.

提出的解决方案

我正在考虑3种方法,所有这些方法都是为了一次处理几个记录:

  1. 使用逐个记录处理 fetchone()

    def sum_scores(dbname, tablename):
      ...
      sum = 0
      for row_num in cur.rowcount:
        row = cur.fetchone()
        sum += score(row)
      ...
      return sum
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用批处理记录处理 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
    
    Run Code Online (Sandbox Code Playgroud)
  3. 依赖游标的迭代器

    def sum_scores(dbname, tablename):
      ...
      sum = 0
      for row in cur:
        sum += score(row)
      ...
      return sum
    
    Run Code Online (Sandbox Code Playgroud)

问题

  1. 我的想法是正确的,因为我提出的3个解决方案一次只会提取可管理大小的数据块吗?或者他们遇到同样的问题fetchall

  2. 对于LARGE数据集,3个提出的解决方案中哪一个可以工作(即计算正确的分数组合而不是在过程中崩溃)?

  3. 游标的迭代器(建议的解决方案#3)如何实际将数据导入Python的内存?一个接一个,分批,或一次一个?

jas*_*str 5

所有这三种解决方案都将起作用,并且只会将结果的一部分存储到内存中。

如果将名称传递给游标,则通过游标进行迭代,提议的解决方案3与提议的解决方案2相同。在游标上进行迭代将获取迭代大小的记录(默认值为2000)。

解决方案#2和#3将比#1快得多,因为连接开销要少得多。

http://initd.org/psycopg/docs/cursor.html#fetch