Забележка:Тази публикация първоначално е публикувана само в нашата електронна книга, Високопроизводителни техники за SQL Server, том 3. Можете да научите за нашите електронни книги тук.
Преди повече от три години написах публикация за опциите на курсора в SQL Server и защо трябва да замените настройките по подразбиране:
- Какво влияние могат да имат различните опции на курсора?
Исках да публикувам продължение, за да повторя, че – въпреки че никога не трябва просто да приемате настройките по подразбиране – наистина трябва да помислите кои опции са най-приложими за вашия сценарий. Исках също да изясня някои неща, които се появиха в коментарите към тази публикация.
Андрю Кели повдигна страхотна точка и това е STATIC
курсорът прави еднократно копие на резултатите, поставя ги в tempdb и след това избягва всякакви проблеми с паралелността, които могат да повлияят на DYNAMIC
курсор. Едната опция не е безспорен победител пред другата във всички случаи; например може да имате много курсори (или курсори с много големи набори от резултати) и/или вече претоварен tempdb и не искате да разтоварвате допълнително напрежение там. Но това е нещо, което си заслужава тестването.
Фабиано също изтъкна страхотна точка, че и двете DYNAMIC
и FAST_FORWARD
курсори може бъдете уязвими към проблема с Хелоуин (обсъждан от Пол Уайт в поредица от 4 части, започваща тук). Пол също коментира, че FAST_FORWARD
може да не е уязвим към проблема, в зависимост от това дали оптимизаторът е избрал статичен или динамичен план (Марк Фридман от Microsoft разглежда много подробности за това тук).
И накрая, исках да отбележа, че не всички курсори по подразбиране са създадени еднакви. Проведох някои тестове и проверих как SQL Server реши да зададе опции за курсора при различни сценарии (проверено с помощта на sys.dm_exec_cursors
функция за динамично управление). Кодът е доста прост:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Ето резултатите за сценариите, които тествах:
Заявката на курсора се основава на... | Тип | Конкурентност | Обхват |
---|---|---|---|
константа (FOR SELECT 1 или FOR SELECT SYSDATETIME() ) | Моментна снимка | Само за четене | Глобално |
a #temp / ##temp таблица | Динамичен | Оптимист | Глобално |
потребителска таблица/изглед | Динамичен | Оптимист | Глобално |
изглед на каталог / DMV | Моментна снимка | Само за четене | Глобално |
присъединяване #tmp -> потребителска таблица/изглед | Динамичен | Оптимист | Глобално |
присъединяване #tmp -> изглед на каталог / DMV | Моментна снимка | Само за четене | Глобално |
присъединяваща се потребителска таблица / изглед -> изглед на каталог / DMV | Моментна снимка | Само за четене | Глобално |
Кредит, на който се дължи кредитът – това разследване беше задействано от отговор от Йерун Мостерт на Stack Overflow.
Така че трябва да сте наясно, че опциите по подразбиране за вашия курсор, ако не ги замените, може да са различни в зависимост от заявката, лежаща в основата на курсора. Ако очаквате конкретно поведение в някой или всички случаи, свикнете изрично да указвате желаните от вас опции.
Но всъщност въпросът е...
... спрете да използвате курсори. Днес наистина има много малко проблеми, при които най-доброто решение е курсор, особено ако сте на SQL Server 2012 или по-добър – където почти всеки проблем, традиционно решаван от курсори, може да бъде решен с помощта на подобрения на функциите на прозореца. Ако все още смятате, че трябва да използвате курсори, моля, вземете съветите в тази публикация и нейния предшественик, за да определите кои опции трябва да използвате.