【发布时间】:2014-10-27 08:02:21
【问题描述】:
为了提供尽可能多的上下文/需要,我正在尝试将存储在远程 postgres 服务器 (heroku) 上的一些数据提取到 pandas DataFrame 中,使用 psycopg2 进行连接。
我对两个特定的表感兴趣,users 和 events,连接工作正常,因为当拉下用户数据时
import pandas.io.sql as sql
# [...]
users = sql.read_sql("SELECT * FROM users", conn)
等待几秒钟后,DataFrame 按预期返回。
<class 'pandas.core.frame.DataFrame'>
Int64Index: 67458 entries, 0 to 67457
Data columns (total 35 columns): [...]
然而,当试图直接从 ipython 中提取更大、更重的 events 数据时,经过很长时间,它就崩溃了:
In [11]: events = sql.read_sql("SELECT * FROM events", conn)
vagrant@data-science-toolbox:~$
当从 iPython 笔记本尝试时,我得到 Dead kernel 错误
内核已经死了,要重新启动它吗?如果不重启内核,可以保存 notebook,但在重新打开 notebook 之前,运行代码将无法运行。
更新 #1:
为了更好地了解我试图引入的 events 表的大小,以下是记录数和每个表的属性数:
In [11]: sql.read_sql("SELECT count(*) FROM events", conn)
Out[11]:
count
0 2711453
In [12]: len(sql.read_sql("SELECT * FROM events LIMIT 1", conn).columns)
Out[12]: 18
更新 #2:
内存绝对是read_sql当前实现的瓶颈:当拉下 events 并尝试运行另一个 iPython 实例时,结果是
vagrant@data-science-toolbox:~$ sudo ipython
-bash: fork: Cannot allocate memory
更新 #3:
我首先尝试了一个 read_sql_chunked 实现,它只返回部分 DataFrame 的数组:
def read_sql_chunked(query, conn, nrows, chunksize=1000):
start = 0
dfs = []
while start < nrows:
df = pd.read_sql("%s LIMIT %s OFFSET %s" % (query, chunksize, start), conn)
start += chunksize
dfs.append(df)
print "Events added: %s to %s of %s" % (start-chunksize, start, nrows)
# print "concatenating dfs"
return dfs
event_dfs = read_sql_chunked("SELECT * FROM events", conn, events_count, 100000)
这很好用,但是当尝试连接 DataFrame 时,内核又死了。
这是在为 VM 提供 2GB RAM 之后。
基于 Andy 对 read_sql 与 read_csv 在实现和性能上的差异的解释,接下来我尝试将记录附加到 CSV 中,然后将它们全部读入 DataFrame:
event_dfs[0].to_csv(path+'new_events.csv', encoding='utf-8')
for df in event_dfs[1:]:
df.to_csv(path+'new_events.csv', mode='a', header=False, encoding='utf-8')
再次,对 CSV 的写入成功完成 - 一个 657MB 的文件 - 但从 CSV 读取从未完成。
由于 2GB 似乎不够用,如何估计多少 RAM 才能读取 657MB 的 CSV 文件?
感觉我缺少对 DataFrames 或 psycopg2 的一些基本理解,但我被困住了,我什至无法确定瓶颈或优化的地方。
从远程(postgres)服务器提取大量数据的正确策略是什么?
【问题讨论】:
-
作为一种体验,这很糟糕!希望我们将来可以为您服务。出于好奇,您的表有多大/有多少行?
-
@AndyHayden 已更新,为 events 表添加了记录数和每个记录的属性数。
-
您是否需要内存中的所有数据?还是在 DataFrame 中同时只有部分数据(例如某些列)就足够了? (但除此之外,您关于数据框有多大的问题当然是合法的)
-
@joris 在这一点上,我同时使用了这两个:几个 DataFrame,其中 18 列的子集非常小,整个数据集分为 28 个部分 DataFrame。至少对于初步探索来说,拥有所有数据似乎是理想的。
-
使用 HDF5 之类的东西(使用 pandas
read_hdf/HDFStore)可以方便快速地按需查询数据子集,如果它太大而无法一次全部拉入内存(很多比 sql 快,并且可以查询子集而不是 csv)
标签: python postgresql pandas psycopg2