poniedziałek, 5 października 2009

Optymalizacja wydajności - przypadek szczególny

Cel:
Traf chciał, że jakiś czas temu powstał kawałek systemu, którego celem było zapamiętanie migawek większej ilości powiązanych tabel (powiązania można określić jako dwa drzewa, połączone za pomocą 2 gałęzi). Głównym powodem powstania była konieczność "zamrożenia" stanu danych na dany moment, możliwością odczytu (za pomocą SQL) kolejnych wersji.

Baza danych
AS400 - IBM - stosowana przez banki, NFZ i mafię kolumbijską. Konkretnie w wersjach od 5.2 do 6.1 (najnowsza)

Struktura:
Tabela główna A z kluczem głównym na 1 polu,
Tabela z historią H - klucz główny na 1 polu - typu DEC(12, 0)

Relacja A <- H (1 do wielu)
Zapis wszystkich danych do tabeli M



Podejście 1:
Realizacja:
Procedura składowana zrzuca dane do jednej tabeli M, gdzie pamiętamy:
a) identyfikator kolejnego uruchomienia procedury
b) typ elementu - wyliczeniowy, definiowany na zewnątrz
c) identyfikator elementu A
d) identyfikator tabeli z historią H

Problemy:
Ilość danych przerosła oczekiwania - w przypadku równoległego uruchomienia 60-100 kopii procedury ilość danych zapisywanych do 1 tabeli osiągała 1 milion rekordów na minutę - baza dawała radę, ale wszystko dookoła zdychało.

Próba rozwiązania:
Ograniczenia w ilości uruchomień, osobna pula połączeń dla procedury generującej.

Wynik:
Z powodu liniowego narastania ilości danych wydajność spadała (również liniowo) - czas wykonania jednej procedury osiągał do 2-3h.



Podejście 2.
Realizacja:
Rozbicie tabeli, do której zapisywane są dane M na wiele tabel - głównie w celu rozbicia obciążenia dysków.

Wynik:
Skok wydajności, ale o wiele mniejszy od oczekiwanego - spowodował powtórne osiągnięcie wydajności takiej jak kilka miesięcy wcześniej.

Problemy:
Ciągle liniowy spadek wydajności z czasem.

Po długiej analizie okazało się, że wiele równolegle puszczonych zapytań typu:

SELECT * FROM H
WHERE H.ID = (SELECT MAX(ID) FROM H WHERE H.ID_A = ID_A)

generuje zdumiewająco duże obciążenie procesora (wszystko po indeksach).



Podejście 3.
Realizacja:
Do tabeli A zostało dodane pole ID_H przechowujące wartość ostatniego rekordu historii.
Podczas zapisu do tabeli H pole A.ID_H jest aktualizowane.

Wynik:
Skok wydajności o około 10 000%... Uśmiechnięty i zadowolony klient, baza danych w końcu odciążona, można realizować kolejne pomysły klienta.




Fanfary, oklaski dla projektanta X (autora pomysłu 3.) , baty dla projektanta Y (autora pierwszego pomysłu), a dla programisty skrzynka piwa - za to, że musiał to wszystko kodować...

Brak komentarzy:

Prześlij komentarz