oracle - 逐页读取Oracle表中的所有数据
问题描述
我有一个非常大的表,有数十亿条记录,我需要从这个表中读取所有数据。希望使用多个线程通过网络连接获取数据。只要这个操作需要时间,如果抓取应用程序能显示一种类似进度条的效果就好了。
我发现标准方法无效,因为 Oracle 需要很长时间才能找到页面的开头。下面是一个慢查询的例子:
select col1
from (select rownum as r, col1 FROM table1 where rownum<20010000)
where r>20000000
有没有更快的方法从这样的表中获取数据?
解决方案
如果没有对系统的深入了解,很难给出建议,所以我只能提供一个基于我成功使用的方法的一般原则。警告:这是老学校。
我在下面的代码示例中使用了伪代码。希望这不会违反任何家规。
有十亿行我猜该表具有唯一/高度选择性的索引。
假设该表有一个名为 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) 以减少到数据库的往返。
推荐阅读
- bash - 使用特殊字符删除 sed 中的特定字符范围
- django - DJango:单个项目中应用程序的多个实例
- sql-server - 查询表中的列表,然后在 select 语句中使用该列表
- nopcommerce - 插入折扣 - NopCommerce 中的 SQL 优惠券
- jquery - dc.js 和 JQuerys 文档准备好不起作用
- entity-framework - 如何使用 EF6 创建限界上下文?
- c# - 存储过程中的动态查询不返回值作为 ASP.Net Core 2.2 中的 DataSet/DataTable
- css - 在不使用 HOC 的情况下覆盖 Material UI 样式?
- typescript - 是否可以保证在 Typescript 中对数组进行排序
- laravel - 如何检查laravel上的这个错误在哪里