如何使用Python处理Oracle数据库中的1000万条记录.(cx_Oracle/Pandas)



我尝试了cx_Oracle包fetchall((,但最终消耗了大量RAM,也尝试过熊猫,但在我们有数十亿记录的情况下,这似乎也没有那么有效。

我的用例-从oracle表中提取每一行到python,进行一些处理并将其加载到另一个表中。PS-期待类似fetchmany((的东西,尝试了这个,但没能让它工作。

对于您的大数据集,因为您的机器的内存是"太小";,然后,您将不得不对行集进行批处理,并在获取下一个集之前重新插入每个集。

调整Cursor.arraysizeCursor.prefetchrows(cx_Oracle 8中的新增功能(对获取性能非常重要。该值用于内部缓冲区大小,无论使用fetchone()还是fetchmany()。请参阅调整cx_Oracle。

重新插入值时使用executemany(),请参阅批处理语句执行和大容量加载。

最大的问题是,你是否需要提取到Python中,或者你是否可以在PL/SQL或SQL中进行操作——使用这两种方法将消除跨网络传输数据的需要,因此效率会高得多。

一般来说,您的策略应该如下。

  1. 编写一个sql查询,获取所需的数据
  2. 执行查询
  3. 循环:从结果中读取元组
  4. 处理元组
  5. 将处理后的内容写入目标关系

但是有很多细节需要处理。

通常,在执行这次的查询时,您会希望读取数据库的一个版本。如果同时对相同的数据进行写入,则会得到一个过时的版本,但不会阻碍写入程序。如果你想要最新的版本,你有一个很难解决的问题。

执行步骤4时,不要打开新的连接,而是重新使用连接。打开一个新的连接就像发射一艘战舰。

最好是在目标关系上没有任何索引,因为每次编写元组时都要支付更新目标关系的费用。它会起作用,但会慢一些。您可以在完成处理后构建索引。

如果这个实现对你来说太慢了,那么加快速度的一个简单方法就是一次处理1000个元组,然后批量写入。如果速度太慢,那么您已经进入了数据库性能调优的黑暗世界。

您可以使用偏移限制属性。如果数据可以按列(主键或列的组合,以便在整个执行过程中数据的顺序相同(排序,下面是我尝试的。

我计算一下这张表的总数。根据区块大小(例如:100000(,创建一个值列表[0,0+chunk,0+chunk2…count(*(]。

例如:如果count(*(=2222,chunk=100,则输出列表为:[0100200,…2222]

然后使用上面列表的值,我通过使用"偏移I行仅获取下一个j值"来获取每个分区。这将在不重叠任何数据的情况下选择分区中的数据。

我在每次迭代中更改I和j的值,以便获得完整的数据。在运行时,给定的块是100000;那么多数据被加载到内存中。您可以根据系统规范将其更改为任何值。

在每次迭代中,将数据保存到您想要的任何位置。

最新更新