MS SQL Procedura składowana przetwarzana na wielu rdzeniach

0

Witam,
jestem nowy na forum i nie mogę znaleźć informacji odnośnie mojego problemu - a wydaje mi się że pewnie powinien się już przewinąć :) Jeśli tak to proszę o informację i z góry przepraszam za duplikowanie tematów.

Chodzi mi mianowicie o wytyczne dotyczące sposobu tworzenia procedury składowanej w MS SQL która mogłaby przetwarzać się równolegle. Jakieś praktyczne wskazówki na przykład :)

Wyobraźcie sobie procedurę wywołującą w sobie wielokrotnie jakąś inną procedurę (nazwijmy ją PROC_B) z parametrem @id (leci sobie po kolei dla @id zawartych w cursorze) - PROC_B coś tam sobie liczy, wywołuje jakieś funkcje, coś tam zmienia w bazie dla tego @id itd. a na koniec zwraca komunikat (b. ważne) odnośnie wyniku przetworzenia @id. W sumie trwa to ok. 2 sek dla jednego wykonania (dla jednego ID). Tyle, że wykonań potrzeba ponad 10 tyś. A wiadomo - jak coś leci po kolei z cursora to kolejne wykonanie jest dopiero po zakończeniu poprzedniego.
Optymalizacja procedury PROC_B wywoływanej dla @id coś tam pewnie jeszcze pomoże - ale nie zmieni faktu że operacja jest mocno długotrwała.
Zaobserwowałem, że podczas przetwarzania wykorzystywany jest tylko jeden rdzeń serwera mającego ich trochę :) - za to obciążony jest w 100% - więc pomyślałem że może warto by było wykorzystać nieco więcej niż jeden na raz. Baza jest MS SQL 2008 Std więc wielordzeniowość obsługuje, operacji dyskowych wiele nie ma więc pole do przyspieszenia całkiem spore.
Problem mam "tylko" taki że nigdy nie pisałem z myślą o wielowątkowości i nie bardzo mogę znaleźć jakieś materiały w temacie. W programowaniu całkiem laikiem nie jestem ale za fachowca też uchodzić nie mogę a szkoły kończyłem gdy o wielu rdzeniach to jeszcze nikt dobrze nie myślał :) Może ktoś mądrzejszy powie jak podejść do tematu?
Teoretycznie wyznaczanie zakresu @id (to co jest w kursorze) mogę przenieść do aplikacji klienckiej pisanej w Delphi - i teoretycznie mogę wówczas uruchamiać kilkanaście połączeń do bazy i wrzucać równolegle kilkanaście wywołań PROC_B dla różnych @id - ale jakieś takie to rozwiązanie mało eleganckie się wydaje - z aplikacji nijak nie poznam ani ilości rdzeni serwera (czyli maksymalnej ilości równolegle przetwarzanych zapytań - swoją drogą z poziomu SQL-a można coś takiego wydobyć?) ani nie pozbędę się narzutu komunikacyjnego (czy to ADO czy inne kontrolki całkiem bezstratne nie są) - a wreszcie pomysł na aplikację był taki żeby była maksymalnie mała od strony końcówki - w przyszłości może być potrzeba przepisania jej np. do dostępnej przez Web-a.

Macie jakieś pomysły?

Pozdrawiam
Artur

0

Generalnie bazy danych nie były pomyślane o przetwarzaniu równoległym przez api (sql). Co innego użycie wielu rdzeni/procesorów przez serwer bazodanowy. Nigdy nie słyszałem o takiej możliwości w ms sql bezpośrednio na poziomie sql, procedury. Możesz zastosować sztuczki używając SSIS.
lub poczytaj http://www.sqlservercentral.com/scripts/T-SQL/68002/
http://blogs.msdn.com/b/sqlperf/archive/2007/05/11/implement-parallel-execution-in-ssis.aspx

Ale ja najpierw zastanowiłbym się nad optymalizacją zapytań i czy ten kursor jest w ogóle potrzebny? Czy nie można uzyskać pewnych wyliczeń przez złączenia etc. Czyli na raz przetwarzać wszystkie rekordy, a nie w kursorze jeden po jednym?

0

Rozumiem, że serwer sam powinien próbować rozłożyć zapytanie na wiele rdzeni?

Może jeśli nieco szczegółowiej napiszę to będzie jaśniej :)

Procedura o której mówię księguje zapisy. Tyle że zapisy mogą dotyczyć różnych rodzajów operacji.
Z aplikacji przychodzi info o zakresie księgowania (filtr na dzień, rodzaj itp).
Wynik filtra leci do kursora - a potem dla każdego zapisu odpalana jest procedura księgująca (sprawdza czy są predekrety ustalajace zasady księgowania, statusy rekordów itp, dopisuje zapisy, zmienia statusy, aktualizuje tabelę przechowującą zbuforowany stan kont etc) - ważne jest żeby użytkownik widział status wykonania operacji księgowania (powodzenie, ostrzeżenie, niepowodzenie) - więc procedura księgująca zwraca status. Lista statusów na koniec przekazywana jest do aplikacji klienckiej.
Wszystko idzie ewidentnie w jednym wątku i wykonuje się na jednym rdzeniu. Nie wiem czy optymalizując poszczególne zapytania jestem w stanie spowodować, że serwer zapędzi do pracy więcej rdzeni? Czy jedynym wyjściem jest (jak pisałem poprzednio) spróbowanie uruchamiania księgowania wielu zapisów równocześnie?

Poradźcie :)
Pozdrawiam
Artur

0

tutaj największym "problemem" dla SZBD jest fakt, że ona nie wie, czy może wykonać to równolegle - tzn. czy przypadkiem operacja na rekordzie z id=1 nie będzie miała wpływu na operację na rekordzie z id=10.

Najprostsze rozwiązanie to odpalić w aplikacji x wątków, każde z własnym połączeniem do bazy i każdy działający na pewnym zakresie danych. Zwróć tylko uwagę, że serwer to nie tylko procesor, który ma kilka rdzeni ale też dysk, na którym są dane, do których te rdzenie muszą się dostać

0

Piszesz rozsądnie - tylko że najprostsze nie zawsze znaczy najlepsze :)
Jak pisałem wcześniej - ideą aplikacji jest to żeby maks operacji wykonywane było przez bazę. A Twój pomysł przenosi jakąś część do samej końcówki aplikacji.

Rozumiem też że na to że sam serwer wykorzysta inne rdzenie to za bardzo liczyć nie mogę.

Pozdrawiam
Artur

1 użytkowników online, w tym zalogowanych: 0, gości: 1