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

时间:2019-01-03 18:19:41

标签: oracle oracle11g

我的表非常庞大,有数十亿条记录,我需要从该表中读取所有数据。期望使用多个线程来通过网络连接获取数据。只要此操作耗时,获取应用程序可以显示类似进度条的状态就很好。

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

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

是否有更快的方法从此类表中获取数据?

1 个答案:

答案 0 :(得分: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之类的语言,我建议将“提取大小”设置为合理的值(512),以减少与数据库的往返行程。