我的表非常庞大,有数十亿条记录,我需要从该表中读取所有数据。期望使用多个线程来通过网络连接获取数据。只要此操作耗时,获取应用程序可以显示类似进度条的状态就很好。
我发现标准方法无效,因为Oracle需要很长时间才能找到页面的开头。以下是慢速查询的示例:
select col1
from (select rownum as r, col1 FROM table1 where rownum<20010000)
where r>20000000
是否有更快的方法从此类表中获取数据?
答案 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),以减少与数据库的往返行程。