首页 > 解决方案 > 逐页读取Oracle表中的所有数据

问题描述

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

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

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

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

标签: oracleoracle11g

解决方案


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

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

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

假设该表有一个名为 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) 以减少到数据库的往返。


推荐阅读