网络
首先,由于无论如何使用rowid和rownum是供应商锁定的,因此您应该考虑使用数据库存储的例程.它可以显着减少将数据从数据库传输到应用程序服务器的开销(特别是如果它们位于不同的计算机上并通过网络连接).
考虑到您有8000万条记录要传输,这可能对您来说是最好的性能提升,尽管它取决于线程所做的工作.
显然,增加带宽也将有助于解决网络问题.
磁盘性能
在更改代码之前,请在任务运行时检查硬盘驱动器负载,也许它只是不能处理那么多的I / O(同时读取10个线程).
迁移到SSD / RAID或群集数据库可能会解决此问题.在这种情况下,更改访问数据库的方式不会.
多线程可以解决CPU问题,但是数据库主要依赖于磁盘系统.
行号
如果要使用rowid和rownum实现它,可能会遇到几个问题.
1)rownum是为每个查询的结果动态生成的.因此,如果查询没有显式
排序,并且每次运行查询时某些记录可能具有不同的行编号.
例如,您第一次运行它并获得如下结果:
some_column | rownum
____________|________
A | 1
B | 2
C | 3
然后您第二次运行它,因为您没有显式排序,所以dbms(出于某种已知的原因)决定返回如下结果:
some_column | rownum
____________|________
C | 1
A | 2
B | 3
2)第一点还意味着,如果要对rownum进行过滤,它将生成包含所有结果的临时表,然后对其进行过滤
因此,rownum不是拆分结果的好选择.尽管rowid看起来更好,但它也存在一些问题.
罗威德
如果查看ROWID description,您可能会注意到“行值唯一地标识数据库中的一行”.
因此,当您删除一行时,在rowid序列中会有一个“洞”,因此rowid在表记录之间的分配可能不均等.
因此,例如,如果您有三个线程,每个线程都提取1’000’000个rowid,则有可能一个线程获得1’000’000条记录,而另外两个则分别获得1条记录.因此,一个将不堪重负,而另外两个则将挨饿.
在您的情况下,这可能没什么大不了的,尽管这很可能是您当前使用主键模式所面临的问题.
或者,如果您首先在调度程序中获取所有rowid,然后将它们平均分配(如peter.petrov建议),那么可以做到这一点,尽管获取8000万id听起来仍然很多,但我认为最好用一个进行拆分返回块边界的sql-query.
或者,您可以通过为每个任务提供少量的Rowid并使用Java 7中引入的Fork-Join框架来解决该问题,但是它是should be used carefully.
同样明显的一点是:rownum和rowid都不能跨数据库移植.
因此,拥有自己的“分片”列会更好,但随后您必须确保自己将记录分成大致相等的块.
还请记住,如果要在多个线程中执行此操作,则检查数据库使用的锁定模式很重要,也许它只是为每次访问锁定表,那么多线程是没有意义的.
正如其他人所建议的那样,您最好首先找到性能低下的主要原因(网络,磁盘,数据库锁定,线程匮乏,或者您只是次优查询-检查查询计划).