Ustawienie Oracle size of row fetches higher sprawia, że moja aplikacja jest wolniejsza?

Jako szczegółowe Tutaj i potwierdzone tutaj , domyślna liczba wierszy zwracanych przez Oracle w czasie zapytań o dane przez JDBC wynosi 10. Pracuję nad aplikacją, która musi czytać i porównywać wiele danych z naszej bazy danych. Myślałem, że jeśli po prostu zwiększyć defaultRowPrefetch być coś jak 1000, to na pewno nasza aplikacja będzie działać szybciej. Jak się okazało, to działał wolniej i o około 20%.

Postanowiliśmy więc powoli zwiększać liczbę z 10 i zobaczyć jak to działa. Widzimy wzrost o 10%, ustawiając go gdzieś pomiędzy 100 a 200. Nigdy bym się jednak nie domyślił, że ustawienie go wyżej sprawi, że nasza aplikacja będzie działać wolniej. Jakieś pomysły, dlaczego tak się stało?

Dzięki!

EDIT:

Dla jasności, używam Oracle 11g R2 i Javy 6.

Edytuj 2:

Ok, chcę powtórzyć moje pytanie, aby było jasne, ponieważ sądząc po odpowiedziach poniżej, nie wyrażam siebie prawidłowo:

Jak to możliwe, że jeśli ustawię większy rozmiar pobierania, moja aplikacja będzie działać wolniej? Dla mnie brzmi to jak powiedzenie: "dajemy Ci szybsze połączenie z Internetem, tj. grubszą rurę, ale przeglądanie stron internetowych będzie wolniejsze.

Wszystkie inne rzeczy są równe, tak jak były w naszych testach, jesteśmy bardzo ciekawi, jak nasza aplikacja może działać gorzej z tylko jedną zmianą.

Author: daveslab, 2012-02-10

6 answers

Możliwe wyjaśnienia:

  1. Java nic nie robi, podczas gdy Oracle oblicza pierwsze 1000 wierszy zamiast pierwszych 10.

  2. Oracle nic nie robi, podczas gdy Java oblicza ostatnie 1000 wierszy zamiast ostatnich 10.

  3. Protokół komunikacyjny (np. TCP/IP) dużo czeka, a następnie musi obsłużyć więcej danych na raz, ale szczytowy transfer danych będzie ograniczany przez ograniczenia sprzętowe. Jest to przeciwdziałane przez protokół nad głową, więc powinien być optymalny rozmiar pobierania i wszystko mniej lub więcej byłoby wolniejsze ;))

  4. Byłoby jeszcze gorzej, gdyby proces pobierania był synchronizowany z innym kodem Javy, tak że Java prosi o więcej wierszy dopiero po przetworzeniu poprzednich danych i Oracle nie robi nic w międzyczasie.

    Wyobraź sobie, że są 3 osoby:

    • pierwszy skÅ‚ada papier A4 na pół
    • [[3]}drugi przynosi stosy zÅ‚ożonego papieru z jednego pokoju do inny
  5. 3rd wycina jakiś kształt ze złożonego papieru.
  6. Jak duże powinny być stosy, jeśli pierwszy musi czekać, aż drugi wróci, a drugi musi czekać, aż trzeci skończy swoją pracę?

    Stosy 1000 nie będą lepsze od stosów 10 chyba;))

 23
Author: Aprillion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 09:42:25

Jak ze wszystkim, nie ma FAST=TRUE ustawienia. Podczas gdy domyślny rozmiar pobierania JDBC 10 nie jest idealny dla twojej sytuacji, jest w porządku dla "typowej" aplikacji OLTP i tak naprawdę nie jest , że również dla Twojego przypadku, wydaje się. Najwyraźniej duży rozmiar aport nie jest idealny dla twojej sytuacji. Ale znowu, to nie jest to źle robić 1000 na raz.

Innym czynnikiem, o którym nie wspomniałeś, jest to, jak szerokie rzędy są ciągnięte. Rozważ to fragment danych pobierany z serwera bazy danych przez sieć do serwera aplikacji to sum(WIDTH*ROWS). Jeśli twoje wiersze mają przekrój 5000 bajtów i ciągniesz 1000 na raz, to każde pobieranie przyniesie 5 MB danych. W innym przypadku, być może twoje wiersze są "chudy" tylko 100 bajtów w poprzek. Następnie pobranie 1000 z nich to tylko 100 tysięcy sztuk.

Ponieważ tylko Ty możesz wiedzieć, jak będą wyglądały dane, zalecamy ustawienie rozmiaru pobierania w całym systemie dla" ogólnego " przypadku, a następnie dostosować kwerendy oddball indywidualnie w razie potrzeby.

Ogólnie rzecz biorąc, ja też znalazłem 100 jako lepsze ustawienie dla dużych procesów danych. To nie jest zalecenie , ale przekazanie obserwacji.

 12
Author: Adam Hawkes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-14 20:05:50

Poprawną metodą {[2] } jest użycie setFetchSize.

Domyślnie, gdy Oracle JDBC uruchamia zapytanie, pobiera zestaw wyników z 10 wierszy na raz od kursora bazy danych. Jest to wartość domyślna Oracle row pobiera wartość rozmiaru. Możesz zmienić liczbę wierszy pobierane przy każdym przejeździe do kursora bazy danych poprzez zmianę wiersza Pobierz wartość rozmiaru.

Standardowy JDBC umożliwia również określenie liczby pobieranych wierszy z każdej bazy danych w obie strony dla zapytanie, a ten numer jest kierowany do rozmiaru aport. W Oracle JDBC używana jest wartość row-prefetch jako domyślny rozmiar pobierania w obiekcie instrukcji. Ustawianie pobierania rozmiar nadpisuje ustawienie row-prefetch i wpływa na kolejne zapytania przeprowadź przez ten obiekt statement.

Rozmiar pobierania jest również używany w zestawie wyników. Po uruchomieniu obiektu polecenia zapytanie, rozmiar fetch obiektu instrukcji jest przekazywany do result set obiekt wytworzony przez zapytanie. Jednak można Ustaw także fetch size w obiekcie result set w celu nadpisania instrukcji fetch rozmiar, który został do niego przekazany.

 6
Author: Adam Musch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-14 19:28:53

BTW, przynajmniej w Oracle musisz uważać na rozmiar pobierania, ponieważ sterownik Oracle odkłada tablicę dla maksymalnego możliwego rozmiaru pobraną przez każdy wiersz, a nie rzeczywisty rozmiar danych. Więc jeśli masz gruby stół, może ucierpieć ślad pamięci.

Spójrz tutaj - http://www.oracle.com/technetwork/database/enterprise-edition/memory.pdf

W Oracle można znaleźć maksymalną możliwą przestrzeń zajmowaną przez kolumnę w tabeli metadanych user_tab_columns (data_length). Może być używany do określenia rozmiaru pobierania.

W trudnych testach stwierdziłem, że 4 * 1024 * 1024 / sum (data_length dla wszystkich kolumn tabeli) jest rozsądnym rozmiarem pobierania.

 6
Author: Sumedh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-14 11:48:43

Prawie to, co powiedział Adam H. - nie ma uniwersalnych ustawień dla każdego rodzaju scenariuszy. Pobieranie wierszy przez Oracle wymaga czasu, więc czas oczekiwania na wiersze po stronie serwera, przed wysłaniem go do klienta, mógłby zostać spędzony w aplikacji, gdyby próg prefetch był ustawiony niżej, więc wydajność spada.

Z tego, co pamiętam, Oracle używa również buforowania po stronie klienta, aby zapewnić przewijalne Kursory. Może pomóc ustawić kursor tylko do przodu, przynajmniej z pamięci. Przynajmniej kiedyś był pomocny w starszych wersjach sterownika JDBC, być może zachowanie się zmieniło od tego czasu.

Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY);
 1
Author: maximdim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-14 19:32:11

Daveslab, trochę więcej informacji...

Jeśli aplikacja potrzebuje całego zestawu wyników, aby rozpocząć przetwarzanie danych, większy rozmiar pobierania może przynieść ulepszenia. Jednak nie ma magicznej liczby, jest konieczne, aby przetestować najbardziej korzystną wartość.

Ustawienie rozmiaru prefetch może mieć wpływ na wydajność aplikacji. Zwiększenie rozmiaru prefetch zmniejszy liczbę podróży w obie strony wymaganych do uzyskania wszystkich danych, ale zwiększy zużycie pamięci. Będzie to zależało od liczba i rozmiar kolumn w zapytaniu oraz liczba wierszy, które mają zostać zwrócone. Będzie to również zależeć od obciążenia pamięci i procesora maszyny klienckiej JDBC. Optimum to samodzielna aplikacja kliencka, która będzie różniła się od mocno załadowanego serwera aplikacji. Należy również wziąć pod uwagę szybkość i opóźnienie połączenia sieciowego.

Klient Oracle JDBC wydaje się wstępnie inicjalizować niektóre struktury pamięci, aby utrzymać pełny rozmiar prefetch . Tak więc, jeśli ustawisz to Rozmiar prefetch 500, 50x przydzielasz dużo pamięci niż gdybyś miał prefetch size = 10. Jest to ogromny dodatkowy popyt na GC, zwłaszcza jeśli nie czytasz tych wierszy. Aby pomyśleć, możesz używać GC 50x częściej niż jest to konieczne, jeśli Zwykle pobierasz tylko kilka wierszy; będzie to miało duży wpływ na responsywność aplikacji .

Jeśli to możliwe, zalecam użycie setFetchSize na podstawie zapytania. Na przykład, jeśli wiesz, że dane zapytanie zwróci tylko kilka wierszy, Ustaw rozmiar na 5. Jeśli wiesz, że zapytanie zwróci 1000 wierszy, Użyj rozmiaru pobierania 100.

Jako heurystyka, istnieją ograniczone korzyści z przekroczenia 50-100.

Mam nadzieję, że rozumiesz, używam Google translator.

 1
Author: tcorteletti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-05 11:49:14