Uwaga:ten post został pierwotnie opublikowany tylko w naszym e-booku, Techniki wysokiej wydajności dla SQL Server, tom 3. Możesz dowiedzieć się o naszych e-bookach tutaj.
Ponad trzy lata temu napisałem post na temat opcji kursora w SQL Server i dlaczego warto zastąpić wartości domyślne:
- Jaki wpływ mogą mieć różne opcje kursora?
Chciałem opublikować kontynuację, aby powtórzyć, że – chociaż nigdy nie powinieneś akceptować ustawień domyślnych – naprawdę powinieneś pomyśleć o tym, które opcje najlepiej pasują do twojego scenariusza. Chciałem również wyjaśnić kilka kwestii, które pojawiły się w komentarzach do tego posta.
Andrew Kelly poruszył świetną kwestię, a mianowicie, że STATIC
kursor tworzy jednorazową kopię wyników, umieszcza je w tempdb, a następnie unika wszelkich problemów ze współbieżnością, które mogą mieć wpływ na DYNAMIC
kursor. Jedna opcja nie zawsze wygrywa z drugą; na przykład możesz mieć wiele kursorów (lub kursorów z bardzo dużymi zestawami wyników) i/lub już przeciążoną bazę danych tempdb i nie chcesz tam odciążać. Ale jest to coś wartego przetestowania.
Fabiano zwrócił również uwagę na to, że zarówno DYNAMIC
i FAST_FORWARD
kursory mogą być podatnym na problem z Halloween (omówiony przez Paula White'a w 4-częściowej serii, zaczynając tutaj). Paul również skomentował, że FAST_FORWARD
może nie być podatny na ten problem, w zależności od tego, czy optymalizator wybrał plan statyczny, czy dynamiczny (Marc Friedman z firmy Microsoft szczegółowo o tym mówi).
Na koniec chciałem zwrócić uwagę, że nie wszystkie domyślne kursory są sobie równe. Przeprowadziłem kilka testów i sprawdziłem, jak SQL Server zdecydował się ustawić opcje kursora w różnych scenariuszach (sprawdzone za pomocą sys.dm_exec_cursors
funkcja dynamicznego zarządzania). Kod jest dość prosty:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Oto wyniki dla scenariuszy, które testowałem:
Zapytanie kursora jest oparte na… | Typ | Współczesność | Zakres |
---|---|---|---|
stała (FOR SELECT 1 lub FOR SELECT SYSDATETIME() ) | Migawka | Tylko do odczytu | Globalny |
tabela #temp / ##temp | Dynamiczny | Optymistyczny | Globalny |
tabela / widok użytkownika | Dynamiczny | Optymistyczny | Globalny |
widok katalogu / DMV | Migawka | Tylko do odczytu | Globalny |
dołączenie #tmp -> tabela / widok użytkownika | Dynamiczny | Optymistyczny | Globalny |
dołączenie #tmp -> widok katalogu / DMV | Migawka | Tylko do odczytu | Globalny |
dołącz tabelę użytkownika / widok -> widok katalogu / DMV | Migawka | Tylko do odczytu | Globalny |
Kredyt, w przypadku którego należy się kredyt – to dochodzenie zostało wywołane odpowiedzią Jeroena Mosterta na Stack Overflow.
Należy więc pamiętać, że domyślne opcje kursora, jeśli ich nie zastąpisz, mogą się różnić w zależności od zapytania będącego podstawą kursora. Jeśli spodziewasz się określonego zachowania w dowolnym lub we wszystkich przypadkach, przyzwyczaj się do wyraźnego określania żądanych opcji.
Ale tak naprawdę chodzi o to…
…przestań używać kursorów. Obecnie jest naprawdę niewiele problemów, w których najlepszym rozwiązaniem jest kursor, zwłaszcza jeśli korzystasz z SQL Server 2012 lub nowszego – gdzie prawie każdy problem tradycyjnie rozwiązywany za pomocą kursorów można rozwiązać za pomocą ulepszeń funkcji okien. Jeśli nadal uważasz, że musisz użyć kursorów, skorzystaj z porad zawartych w tym poście i jego poprzedniku, aby określić, których opcji powinieneś użyć.