2011-07-09 64 views
4

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

我首先想到得到的所有记录的计数和做的:

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

,但没有奏效。现在我卡住了。

任何帮助将不胜感激。

回答

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; 
+1

这赢得了*并发执行。分成十份工作,第十份工作将选择所有行并丢弃其中的90%,第九份工作将选择总行的十分之九并丢弃其中大部分,等等。这将比运行单个线程花费更多的精力,并且不会更快。可能它会变慢。 – APC

3

确定查询的并行执行会更快?如果巨大的表存储在具有多个磁盘的磁盘阵列中,或者它被分区到多个磁盘上,情况就会如此。在其他所有情况下,表格的顺序访问速度会快很多倍。

如果您确实需要拆分查询,则必须以某种方式对其进行拆分,以便每个零件的顺序访问仍是可能的。请发布表的DLL,以便我们可以给出具体的答案。

如果将数据处理或加载到数据网格中是瓶颈,那么您最好是使用单个进程读取数据,并在进一步处理数据之前对数据进行分割。

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

-1

你有没有考虑过在ROWNUM上使用MOD 10来将数据每次抽出十分之一?

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

这不适合*并发执行。每次执行都将发出全表扫描。此外,如果没有ORDER BY,则不能保证每个线程都会返回一个不同的队列。将'MOD()'应用于数字主键仍然会执行十个全表扫描,但至少它会捕获整个表格。无论哪种方式,执行全表扫描的十个线程比执行一次全表扫描的单个线程差得多。 – APC

+1

-1 SQL>选择。* 2从ALL_OBJECTS一个 3,其中MOD(ROWNUM,10)= 0 4/ 没有行选择用 –

5

如果有企业版许可证,实现这一目标的最简单的方法是并行查询。

对于一次性或即席查询使用并行提示:

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它为我们自动化了这一点。

+0

同意DBMS_PARALLEL_EXECUTE – pahariayogi