Spis treści:

Kategoria:SQL Server


Opóźnienie wykonywania skryptu SQL - WAITFOR

SQL Server posiada w swoich zasobach pewną funkcję, która jest raczej rzadko wykorzystywana. Pozwala ona na wykonywanie skryptów w pewnych określonych odstępach czasu, lub o konkretnej godzinie. Przypuśćmy, że chcemy wykonać jedną operację, a za godzinę inną operację. Jak można sobie poradzić? Istnieje przynajmniej kilka metod, wśród których można wspomnieć chociażby zaplanowane zadania lub powszechnie stosowane zewnętrzne aplikacje. Dla najprostszych zadań idealnie nadaje się instrukcja WAITFOR. Jak ona działa?

PAUSE, SLEEP, WAIT, czyli jak uśpić SQL Server

Instrukcja WAITFOR ma kilka możliwych wariantów. Zamiast opisywać po kolei wszystkie możliwości, przedstawię je za pomocą skryptów. Przyjrzyjmy się zatem pierwszemu z nich:

SELECT GETDATE()
WAITFOR DELAY '00:00:01'
SELECT GETDATE()

Wynikiem działania poniższego skryptu będzie rezultat podobny do tego poniżej:

(No column name)
2011-06-21 13:58:38.210
(No column name)
2011-06-21 13:58:39.210

Wyjaśnię, co jest tutaj według mnie istotne. Po pierwsze, wynik drugiego zapytania zwróci datę o sekundę późniejszą niż wynik pierwszego zapytania - to właśnie efekt działania instrukcji WAITFOR. Parametrem występującym po DELAY, będącym częścią instrukcji, jest czas w formacie GG:MM:SS.mmm, gdzie GG to liczba godzin (dwie cyfry), MM liczba minut (dwie cyfry), SS liczba sekund (dwie cyfry), a mmm to liczba milisekund (3 cyfry). Gdybyśmy zatem chcieli zatrzymać wykonywanie się instrukcji na jedną godziną, dwie minuty, trzy sekundy i 456 milisekund, wtedy napiszemy:

SELECT GETDATE()
WAITFOR DELAY '01:02:03.456'
SELECT GETDATE()

Jeżeli wartość godzin, minut lub sekund jest jednocyfrowa, można pominąć wiodące zera. W ostatnim przykładzie byłoby to więc '1:2:3.456'.

Warto zauważyć, że wynik pierwszej instrukcji wyświetlany jest przez Management Studio dopiero wtedy, gdy zakończy się druga instrukcja SELECT. Można temu zaradzić używając instrukcji GO. Instrukcja przyjmie więc następującą postać:

SELECT GETDATE()
GO
WAITFOR DELAY '00:00:01'
SELECT GETDATE()

Wykonanie się instrukcji o konkretnej godzinie

Instrukcja WAITFOR jak wspomniałem może być wykorzystywana na kilka sposobów. Oprócz technik wykorzystujących Service Brokera stosuje się ją do określenia czasu wykonania się konkretnej instrukcji. Składnia będzie wyglądała następująco:

WAITFOR TIME '14:00:00'
SELECT GETDATE()

Tym razem po WAITFOR występuje słowo kluczowe TIME, a następnie czas w formacie GG:MM:SS.mmm, czyli takim samym jak przy DELAY.

Jakie są konsekwencje?

Po poierwsze - gdy wykonuje się instrukcja WAITFOR, cały czas działa transakcja. Co prada nie blokuje ona procesora i nie wykorzystuje jego mocy obliczeniowej, ale zajmuje wątek. Po drugie, instrukcja nie jest sczególnie precyzyjna, bo jej działania zależy od zajętości procesora i całego serwera. Testując powyższe instrukcje można zauważyć, że sekunda może trwać rzeczywiście sekundę, ale może też trwać nieco dłużej.

Każda instrukcja WAITFOR blokuje jeden wątek systemu operacyjnego. Nie należy w związku z tym uruchamiać wiele takich instrukcji, bo może to niekorzystnie wpłynąć na wydajność całego serwera.

Ostatnie ostrzeżenie jest chyba najważniejsze - należy unikać instrukcji WAITFOR, gdy jakieś obszary bazy danych są zablokowane przez transakcje. Zablokowanie tabeli przez WAITFOR sprawi, że nie będzie możliwe jakiekolwiek wykorzystanie tej tabeli w innych równoległych zapytaniach. Jest to o tyle istotne, że instrukcja WAITFOR może trwaćbardzo długo.

Kategoria:SQL Server

, 2013-12-20

Komentarze:

MJK (2013-07-31 11:41:44)
Codziennie sprawdzam czy wszystkie rekordy weszły do bazy, a import potrafi trwać nawet 20 minut.
Zamiast puszczać "select COUNT...." co parę minut i patrzeć czy ilości się dalej zwiększają ustawię ponawianie komendy w krótkich przedziałach czasowych a wynik będzie się sam pojawiał.
Nie mam jeszcze pomysłu na wykorzystanie "WAITFOR TIME..." w mojej pracy ale warto wiedzieć że można coś takiego zrobić, a pomysł znajdzie się w miarę potrzeb.
PD (2013-08-01 13:19:07)
To może ja podsunę pomysł na wykorzystanie WAITFOR TIME:

WAITFOR TIME (czwarta nad ranem) [Przebuduj indeksy bo mały ruch] :)

Nie trzeba uruchamiać zadań ani wstawać z łóżka.
Dodaj komentarz
Wyślij
Ostatnie komentarze
Dzieki za rozjasnienie zagadnienia upsert. wlasnie sie ucze programowania :).
Co się stanie gdy spróbuję wyszukać:
SELECT * FROM NV_Airport WHERE Code='SVO'
SELECT * FROM V_Airport WHERE Code=N'SVO'
(odwrotnie są te N-ki)
Będzie konwersja czy nie znajdzie żadnego rekordu?