问题描述
我有以下代码,该代码查询约50万行的数据库。并在命中rows = cur.fetchall()
时抛出SIGKILL。我试图遍历游标而不是将其全部加载到行中,但是它似乎仍然会引起OOM问题。
无论表的大小如何,我如何才能从数据库中获取所有数据并将其安全地转换为实木复合地板文件?
def get_parquet_for_dataset_id(self,dataset,lob,max_dt):
query = _table_query(lob,table_name,max_dt)
conn = self.conns[lob]
with conn:
with conn.cursor(cursor_factory=extras.RealDictCursor) as cur:
cur.execute(query)
rows = cur.fetchall()
table = rows_to_table(rows)
pq_bytes = io.BytesIO()
pq.write_table(table,pq_bytes)
_ = pq_bytes.seek(0)
return pq_bytes;
解决方法
服务器端游标,请参见here:
执行数据库查询时,Psycopg游标通常会获取后端返回的所有记录,并将它们转移到客户端进程。如果查询返回了大量数据,则客户端将按比例分配大量内存。
如果数据集太大而无法在客户端实际处理,则可以创建服务器端游标。使用这种游标,可以仅将受控量的数据传输到客户端,从而可以检查大型数据集而无需将其完全保留在内存中。