从Oracle读取包含数百万行的大表并写入HDF5

时间:2013-12-16 18:50:38

标签: python pandas hdf5 pytables

我正在使用具有数百万行和100多列的Oracle数据库。我试图使用带有索引的某些列的pytables将这些数据存储在HDF5文件中。我将在pandas DataFrame中读取这些数据的子集并执行计算。

我尝试过以下方法:

下载表,使用实用程序到csv文件中,使用pandas按块读取csv文件块,然后使用pandas.HDFStore附加到HDF5表。我创建了一个dtype定义并提供了最大字符串大小。

但是,现在当我尝试直接从Oracle DB下载数据并通过pandas.HDFStore将其发布到HDF5文件时,我遇到了一些问题。

pandas.io.sql.read_frame不支持分块阅读。我没有足够的RAM来首先将整个数据下载到内存中。

如果我尝试使用具有固定数量记录的cursor.fecthmany(),则数据库表中的读取操作需要很长时间,而且我必须读取属于日期范围的记录。我正在使用DataFrame(cursor.fetchmany(), columns = ['a','b','c'], dtype=my_dtype) 但是,创建的DataFrame总是推断dtype而不是强制执行我提供的dtype(与read_csv不同,它遵循我提供的dtype)。因此,当我将此DataFrame附加到已存在的HDFDatastore时,存在类型不匹配的问题。 float64可能会在一个块中解释为int64。

感谢你们能否提出你的想法并指出我正确的方向。

2 个答案:

答案 0 :(得分:1)

嗯,目前唯一实用的解决方案是直接使用PyTables,因为它专为内存不足而设计......这有点单调乏味但不是那么糟糕:

http://www.pytables.org/moin/HintsForSQLUsers#Insertingdata

使用Pandas的另一种方法是:

"Large data" work flows using pandas

答案 1 :(得分:0)

好的,所以我对oracle数据库没有多少经验,但这里有一些想法:

来自oracle的任何特定记录的访问时间都很慢,因为缺少索引,并且您希望数据按时间戳顺序排列。

首先,您无法为数据库启用索引编制?

如果你无法操纵数据库,你可能会请求一个只包含每行的有序唯一ID的搜索结果集?

您可以将此数据存储为单个唯一ID数组,并且您应该能够适应内存。如果您为每个唯一键允许4k(保守估计,包括开销等),并且您没有保留时间戳,那么它只是一个整数数组,它可能会耗费大约1.1GB的RAM用于300万条记录。这不是一堆,可能你只想要一个活动数据的小窗口,或者你可能正在逐行处理?

使用生成器功能来完成所有这些操作。这样,一旦你完成迭代,它应该释放内存,而不必去任何东西,它也使你的代码更容易遵循,并避免膨胀计算循环的实际重要逻辑。

如果你不能将它全部存储在内存中,或者由于某些其他原因这不起作用,那么你能做的最好的事情就是弄清楚你可以在内存中存储多少。您可以将作业分成多个请求,并在最后一个请求完成后使用多线程发送请求,同时将数据处理到新文件中。在您要求返回数据之前,它不应该耗尽内存。如果延迟是正在完成的请求或正在下载的数据,请尝试并确定。

从它的声音中,你可能会抽象数据库,让pandas发出请求。值得看看它如何限制结果。您应该能够对所有数据发出请求,但只能从数据库服务器一次加载一行结果。