我有一个包含大约30,000,000行的表,我需要迭代,分别操作每行的数据,然后将数据从行保存到本地驱动器上的文件中。
使用SQL for Oracle循环遍历表中所有行的最有效方法是什么?我一直在谷歌搜索,但没有看到这样做的直接方式。请帮忙。请记住,我不知道确切的行数,只是估计值。
编辑澄清:
我相信我们正在使用Oracle 10g。行数据包含blob数据(压缩文本文件和xml文件),这些数据将被读入内存并加载到自定义对象中,然后使用.Net DOM访问类进行更新/转换,重新压缩并存储到本地驱动器上
我没有太多的数据库经验 - 我计划在ADO.Net + OracleCommands中使用直接的SQL语句。没有性能限制。这是供内部使用的。我只想以最好的方式做到这一点。
答案 0 :(得分:2)
您需要从Oracle DB读取30m行,并将每行中的BLOB(每行一个BLOB列中的一个压缩XML /文本文件?)中的30m文件写入本地计算机上的文件系统?
显而易见的解决方案是在SELECT * FROM tbl WHERE <range>
上打开一个ADO.NET DataReader,这样你就可以进行批量处理。从阅读器读取BLOB到您的API,做你的东西并写出文件。我可能会尝试编写程序,以便它可以从许多计算机上运行,每个计算机都有自己的范围 - 你的瓶颈很可能是解压缩,操作和重新压缩,因为许多消费者可能会从该表中流式传输数据服务器对服务器性能没有明显影响。
我怀疑你是否能够通过Oracle数据库内部的基于集合的操作来实现这一点,我也会考虑文件系统以及如何组织这么多文件(以及你是否有空间 - 记住文件系统上文件占用的大小始终是文件系统块大小的偶数倍。)
答案 1 :(得分:1)
您可以尝试使用rownum查询来获取块,直到您获取不存在的块。
这是关于rownum查询的好文章: http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html
如果您不想阅读,请直接跳到末尾的“使用ROWNUM的分页”部分进行示例查询。
答案 2 :(得分:1)
我最初的解决方案是做这样的事情,因为我可以访问id号码(伪代码):
int num_rows = 100;
int base = 0;
int ceiling = num_rows;
select * from MY_TABLE where id >= base and id < ceiling;
iterate through retrieved rows, do work,
base = ceiling;
ceiling += num_rows;
select * from MY_TABLE where id >= base and id < ceiling;
iterate through retrieved rows, do work,
...etc.
但我觉得这可能不是最有效或最好的方法......
答案 3 :(得分:0)
在处理大量行时,最好使用基于集合的操作。
然后,您将享受到性能优势。处理完数据后,您应该可以一次性将表中的数据转储到文件中。
这的可行性取决于您需要对行执行的处理,尽管在大多数情况下可以避免使用循环。是否有一些特定的要求会阻止您一次处理所有行?
如果遍历行是不可避免的,使用批量绑定可能是有益的:FORALL批量操作或BULK COLLECT用于“选择进入”查询。
答案 4 :(得分:0)
听起来你需要整个数据集之前你可以进行任何数据操作,因为它是BLOB&gt;。我只是使用DataAdapter.Fill,然后将数据集交给自定义对象进行迭代,执行操作,然后将结束对象写入磁盘,然后压缩。