Sieć
Po pierwsze, ponieważ używam rowid i rownum i tak jest zablokowany przez dostawcę, powinieneś rozważyć użycie procedur przechowywanych w bazie danych. Może to znacznie zmniejszyć obciążenie związane z transmisją danych z bazy danych do serwera aplikacji (zwłaszcza jeśli znajdują się one na różnych maszynach i są połączone przez sieć).
Biorąc pod uwagę, że masz 80 milionów rekordów do przesłania, może to być dla Ciebie najlepszy wzrost wydajności, choć zależy to od rodzaju pracy, jaką wykonują Twoje wątki.
Oczywiście zwiększenie przepustowości pomogłoby również rozwiązać problemy z siecią.
Wydajność dysku
Przed wprowadzeniem zmian w kodzie sprawdź obciążenie dysku twardego podczas wykonywania zadań, być może po prostu nie poradzi sobie z tak dużą ilością operacji we/wy (10 wątków czytających jednocześnie).
Migracja do bazy danych SSD/RAID lub klastrowania może rozwiązać problem. W takim przypadku zmiana sposobu dostępu do bazy danych nie nastąpi.
Wielowątkowość może rozwiązać problemy z procesorem, ale bazy danych zależą głównie od systemu dyskowego.
Równa
Istnieje kilka problemów, z którymi możesz się zmierzyć, jeśli będziesz wdrażać go za pomocą rowid i rownum.
1) rownum jest generowany na bieżąco dla wyników każdego zapytania. Więc jeśli zapytanie nie ma jawnego sortowania i możliwe jest, że niektóre rekordy mają inny numer wiersza za każdym razem, gdy uruchamiasz zapytanie.
Na przykład uruchamiasz go za pierwszym razem i otrzymujesz takie wyniki:
some_column | rownum
____________|________
A | 1
B | 2
C | 3
następnie uruchamiasz go po raz drugi, ponieważ nie masz jawnego sortowania, dbms (z jakiegoś znanego sobie powodu) decyduje się zwrócić wyniki w następujący sposób:
some_column | rownum
____________|________
C | 1
A | 2
B | 3
2) punkt 1 oznacza również, że jeśli będziesz filtrować wyniki na rownum wygeneruje tymczasową tabelę z WSZYSTKO wyniki, a następnie filtruj
Więc rownum nie jest dobrym wyborem do dzielenia wyników. Podczas gdy rowid wydawało się lepsze, ma też pewne problemy.
Rowid
Jeśli spojrzysz na opis ROWID możesz zauważyć, że „wartość wierszad jednoznacznie identyfikuje wiersz w bazie danych ".
Z tego powodu oraz z faktu, że po usunięciu wiersza masz „dziurę” w sekwencji wierszy, wiersze mogą być rozłożone nierównomiernie między rekordami tabeli.
Na przykład, jeśli masz trzy wątki, a każdy z nich pobiera 1 000 000 wierszy, możliwe jest, że jeden otrzyma 1 000 000 rekordów, a pozostałe dwa po 1 rekordzie. Więc jeden będzie przytłoczony, a dwóch innych głoduje .
Może to nie być wielka sprawa w twoim przypadku, chociaż bardzo dobrze może to być problem, z którym masz obecnie do czynienia ze wzorcem klucza podstawowego.
Lub jeśli najpierw pobierzesz wszystkie rowidy w dyspozytorze, a następnie podzielisz je równo (jak sugerował Piotr.Pietrow), co może załatwić sprawę, chociaż pobranie 80 milionów identyfikatorów nadal brzmi jak dużo, myślę, że lepiej byłoby zrobić dzielenie za pomocą jednego sql-query, który zwraca granice porcji.
Lub możesz rozwiązać ten problem, podając małą liczbę wierszy na zadanie i używając frameworka Fork-Join wprowadzonego w Javie 7, jednak powinien być używane ostrożnie .
Również oczywisty punkt:zarówno rownum, jak i rowid nie są przenośne między bazami danych.
Dlatego znacznie lepiej jest mieć własną kolumnę „sharding”, ale wtedy będziesz musiał się upewnić, że dzieli ona rekordy na mniej więcej równe części.
Pamiętaj również, że jeśli zamierzasz to zrobić w kilku wątkach, ważne jest sprawdzenie, jakiego baza danych używa trybu blokowania , być może po prostu blokuje tabelę dla każdego dostępu, wtedy wielowątkowość nie ma sensu.
Jak sugerowali inni, lepiej najpierw znajdź główną przyczynę niskiej wydajności (blokowanie sieci, dysków, bazy danych, głód wątków, a może po prostu masz nieoptymalne zapytania - sprawdź plany zapytań).