如何将海量数据查询拆分为多个查询

时间:2011-07-09 10:05:13

标签: sql oracle select

我必须从包含数百万行的表中选择所有行(以预加载Coherence数据网格。)如何将此查询拆分为多个可以由多个线程并发执行的查询?

我首先考虑计算所有记录并进行操作:

SELECT ... 
WHERE ROWNUM BETWEEN (packetNo * packetSize) AND ((packetNo + 1) * packetSize)

但这不起作用。现在我被卡住了。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:5)

如果您拥有Enterprise Edition许可证,则实现此目标的最简单方法是并行查询。

对于一次性或即席查询,请使用PARALLEL提示:

select /*+ parallel(your_table, 4) */  *
from your_table
/

提示中的数字是您要执行的从属查询的数量;在这种情况下,数据库将运行四个线程。

如果希望表上发出的每个查询都可并行化,则永久更改表定义:

alter table your_table parallel (degree 4)
/

请注意,数据库不会始终使用并行查询;优化器将决定它是否合适。并行查询仅适用于跨越多个分区的全表扫描或索引范围扫描。

有一些警告。并行查询要求我们有足够的内核来满足建议的线程数;如果我们只有一个双核CPU设置,并行度为16则不会神奇地加速查询。另外,我们需要备用CPU容量;如果服务器已经受CPU限制,那么并行执行只会让事情变得更糟。最后,I / O和存储子系统需要能够满足并发需求; SAN在这里可能非常缺乏帮助。

与性能问题一样,在投入生产之前,在代表性环境中针对实际数据量进行一些基准测试至关重要。


如果您没有企业版怎么办?嗯,有可能手工模仿并行执行。 Tom Kyte称之为“自己动手并行”。我自己使用过这种技术,效果很好。

关键是要计算出适用于表格的总范围ROWID,并将它们分成多个作业。与此线程中提出的其他一些解决方案不同,每个作业只选择所需的行。 Kyte先生在一个旧的AskTom线程中总结了这项技术,包括重要的分割脚本:find it here

分割表格并启动线程是一项手动任务:一次性罚款,但经常做的很烦人。因此,如果您运行11g第2版,您应该知道有一个新的PL / SQL包DBMS_PARALLEL_EXECUTE可以为我们自动执行此操作。

答案 1 :(得分:3)

您确定查询的并行执行会更快吗?只有当巨大的表存储在具有许多磁盘的磁盘阵列上或者如果它被分区在多个磁盘上时,才会出现这种情况。在所有其他情况下,表的顺序访问将快许多倍。

如果您真的必须拆分查询,则必须以某种方式拆分它,以便仍然可以对每个部件进行顺序访问。请发布表格的DLL,以便我们给出具体答案。

如果处理数据或加载到数据网格是瓶颈,那么最好用一个进程读取数据并在进一步处理数据之前拆分数据。

假设读取速度很快并且进一步的数据处理是瓶颈,您可以例外读取数据并将其写入非常简单的文本文件(如固定长度或CSV)。在每10,000行之后,您将启动一个新文件并生成一个线程或进程来处理刚刚完成的文件。

答案 2 :(得分:0)

尝试这样的事情:

select * from 
( select a.*, ROWNUM rnum from 
  ( <your_query_goes_here, with order by> ) a 
  where ROWNUM <= :MAX_ROW_TO_FETCH )
where rnum  >= :MIN_ROW_TO_FETCH;

答案 3 :(得分:-1)

您是否考虑过在ROWNUM上使用MOD 10来一次提取十分之一的数据?

SELECT A.*
FROM Table A
WHERE MOD(ROWNUM,10) = 0;