Мрежа
Първо, откакто използвам rowid и rownum така или иначе е vendor-lock, трябва да обмислите използването на съхранени рутинни бази данни. Това може значително да намали разходите за предаване на данни от базата данни към сървъра на приложения (особено ако те са на различни машини и са свързани чрез мрежа).
Като се има предвид, че имате 80 милиона записа за предаване, това може да е най-доброто повишаване на производителността за вас, въпреки че зависи от вида на работата, която вършат вашите нишки.
Очевидно увеличаването на честотната лента също би помогнало за разрешаване на мрежови проблеми.
Ефективност на диска
Преди да направите промени в кода, проверете натоварването на твърдия диск, докато задачите се изпълняват, може би той просто не може да се справи с толкова I/O (10 нишки, които четат едновременно).
Мигрирането към SSD/RAID или клъстерна база данни може да реши проблема. Въпреки че промяната на начина, по който имате достъп до базата данни, няма да стане в този случай.
Многонишковостта може да реши проблеми с процесора, но базите данни зависят най-вече от дисковата система.
Rownum
Има няколко проблема, с които може да се сблъскате, ако ще го прилагате с помощта на rowid и rownum.
1) rownum се генерира в движение за резултатите от всяка заявка. Така че, ако заявката няма изрично сортиране и е възможно някои записи да имат различен номер на ред всеки път, когато стартирате заявка.
Например, стартирате го за първи път и получавате резултати като този:
some_column | rownum
____________|________
A | 1
B | 2
C | 3
след това го стартирате втори път, тъй като нямате изрично сортиране, dbms (по някаква причина, известна на себе си) решава да върне резултати като този:
some_column | rownum
____________|________
C | 1
A | 2
B | 3
2) точка 1 също предполага, че ако ще филтрирате резултатите на rownum ще генерира временна таблица с ВСИЧКИ резултати и след това го филтрирайте
И така rownum не е добър избор за разделяне на резултатите. Докато rowid изглеждаше по-добре, има и някои проблеми.
Rowid
Ако погледнете Описанието на ROWID може да забележите, че „стойността на rowid уникално идентифицира ред в базата данни ".
Поради това и факта, че когато изтриете ред, имате "дупка" в последователността на редове, редовете може да не са разпределени поравно между записите в таблицата.
Така например, ако имате три нишки и всяка извлича 1 000 000 реда, е възможно една да получи 1 000 000 записа, а други две по 1 запис. Така един ще бъде претоварен, докато други двама гладуват .
Може да не е голяма работа във вашия случай, въпреки че много добре може да е проблемът, с който се сблъсквате в момента с модела на първичен ключ.
Или ако първо извлечете всички редове в dispatcher и след това ги разделите поравно (както peter.petrov предложи), това може да свърши работа, въпреки че извличането на 80 милиона идентификатори все още звучи като много, мисля, че би било по-добре да направите разделянето с един sql-заявка, която връща граници на парчета.
Или можете да разрешите този проблем, като дадете малък брой редове на задача и използвате рамката Fork-Join, въведена в Java 7, но тя трябва да бъде used внимателно .
Също така очевидна точка:както rownum, така и rowid не са преносими между бази данни.
Така че е много по-добре да имате своя собствена колона "sharding", но тогава ще трябва сами да се уверите, че тя разделя записите на повече или по-малко равни части.
Също така имайте предвид, че ако ще го правите в няколко нишки, е важно да проверите какъв база данни използва режим на заключване , може би просто заключва таблицата за всеки достъп, тогава многонишковостта е безсмислена.
Както предложиха други, по-добре първо да откриете каква е основната причина за ниската производителност (мрежа, диск, заключване на база данни, липса на нишка или може би просто имате неоптимални заявки - проверете плановете за заявки).