逐页读取Oracle表中的所有数据

Posted

技术标签:

【中文标题】逐页读取Oracle表中的所有数据【英文标题】:Read all the data from Oracle table page-by-page 【发布时间】:2019-01-03 18:19:41 【问题描述】:

我有一个非常大的表,其中包含数十亿条记录,我需要从该表中读取所有数据。希望使用多个线程通过网络连接获取数据。只要这个操作需要时间,如果抓取应用程序能显示一种类似进度条的效果就好了。

我发现标准方法无效,因为 Oracle 需要很长时间才能找到页面的开头。下面是慢查询的例子:

select col1 
from (select rownum as r, col1 FROM table1 where rownum<20010000) 
where r>20000000

有没有更快的方法从这样的表中获取数据?

【问题讨论】:

为什么需要读取所有十亿行?你作为一个人没有,也不能......所以我想我要问的是,你打算用所有这些数据做什么? 我需要转换它并加载到另一个数据库中 你打算怎么改造它,你打算把它放到另一个oracle数据库中吗? 应用程序负责转换并将数据加载到非 Oracle 数据库中。 我想说在 db 中的 plsql 中进行转换 - 在那里可能会更快 - 然后你可以使用 utl 文件将数据的分隔文本文件写入服务器文件系统 【参考方案1】:

如果对系统没有深入了解,很难给出建议,所以我只能提供一个基于我成功使用的方法的一般原则。警告:这是老学校。

我在下面的代码示例中使用了伪代码。希望这不会违反任何家规。

有十亿行我猜该表具有唯一/高度选择性的索引。

假设该表有一个名为 ID 的列具有唯一索引,我会执行以下操作:

SELECT MIN(ID) minid, MAX(ID) maxid, COUNT(1) numid FROM the_Table;

这为我们提供了基本的高级信息来计划我们的攻击。

接下来,你可以运行多少个进程? 7?

那么,假设分布相当均匀:

thread_size = numid / processes

如果thread_size 大得吓人,将其进一步拆分为我们可管理的 100k 行。目的是获取 SELECT 中使用的索引。

有了它,编写过程如下:

process_batch ( batchStartID, batchEndID )

   SELECT * FROM the_table WHERE id BETWEEN batchStartID and batchEndID ;
   do_row_by_row_processing ( rowdata );
   write_progress_info)every_1000_rows();


process_thread ( startID, endID, batchSize )

   theID = startID;
   while ( theID < endID )
   
      process_batch ( theID, theID+batchSize);
      write_thread_progress_info(theID, startID, endID);
      theID = theID + batchSize + 1;
   

每个process_thread 实例都有一个唯一的范围和批量大小。

它分批处理(endID-startID)batchSize

process_batch 将利用索引将其处理限制为相对较少的行数。返回的结果将写入您的文件。

然后你启动几个具有适当偶数范围的 process_threads。

这种方法的一个好处是,如果任何地方出现故障,您都可以在故障范围内重新启动。

您还可以获得每次迭代的大致进度标记。

如果在提取应用程序中使用 Java 之类的语言,我建议将 Fetch Size 设置为合理的值 (512),以减少到数据库的往返。

【讨论】:

以上是关于逐页读取Oracle表中的所有数据的主要内容,如果未能解决你的问题,请参考以下文章

oracle语句,我想查询A表中的a字段下的值不等于B表中b的值的数据,

oracle中只读取一条数据,怎么写

在oracle中如何将一个表中所有数据加到另一个表中

在oracle怎样更新表中的数据

从数据库系统表中选择所有索引,根据Oracle中的索引聚合数据

Oracle - 我想找出数据库表中的增量变化