Bemærk:Dette indlæg blev oprindeligt kun offentliggjort i vores e-bog, High Performance Techniques for SQL Server, bind 3. Du kan finde ud af om vores e-bøger her.
For over tre år siden skrev jeg et indlæg om markørindstillinger i SQL Server, og hvorfor du bør tilsidesætte standardindstillingerne:
- Hvilken indflydelse kan forskellige markørindstillinger have?
Jeg ville sende en opfølgning for at gentage, at – selvom du aldrig bare skal acceptere standardindstillingerne – bør du virkelig tænke over, hvilke muligheder der er mest anvendelige for dit scenarie. Jeg ønskede også at præcisere et par punkter, der kom op i kommentarerne til det indlæg.
Andrew Kelly kom med en god pointe, og det er en STATIC
markøren laver en engangskopi af resultaterne, sætter dem i tempdb og undgår derefter eventuelle samtidighedsproblemer, der kan påvirke en DYNAMIC
cursoren. Den ene mulighed er ikke en klar vinder over den anden i alle tilfælde; for eksempel kan du have mange markører (eller markører med meget store resultatsæt) og/eller en allerede overbebyrdet tempdb og ønsker ikke at aflaste yderligere stress der. Men det er noget, der er værd at teste.
Fabiano kom også med et godt punkt, som både DYNAMIC
og FAST_FORWARD
markører kan være sårbar over for Halloween-problemet (diskuteret af Paul White i en 4-delt serie, der starter her). Paul kommenterede også, at FAST_FORWARD
er muligvis ikke sårbar over for problemet, afhængigt af om optimeringsværktøjet valgte en statisk eller dynamisk plan (Microsofts Marc Friedman går i detaljer om det her).
Til sidst ville jeg påpege, at ikke alle standardmarkører er skabt lige. Jeg kørte nogle tests og tjekkede, hvordan SQL Server besluttede at indstille markørindstillinger under en række scenarier (valideret ved hjælp af sys.dm_exec_cursors
dynamisk ledelsesfunktion). Koden er ret simpel:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Her er resultaterne for de scenarier, jeg testede:
Markørforespørgsel er baseret på... | Typ | Samtidig | Omfang |
---|---|---|---|
en konstant (FOR SELECT 1 eller FOR SELECT SYSDATETIME() ) | Snapshot | Skrivebeskyttet | Global |
en #temp / ##temp tabel | Dynamisk | Optimistisk | Global |
en brugertabel / visning | Dynamisk | Optimistisk | Global |
en katalogvisning / DMV | Snapshot | Skrivebeskyttet | Global |
a join #tmp -> brugertabel / view | Dynamisk | Optimistisk | Global |
a join #tmp -> katalogvisning / DMV | Snapshot | Skrivebeskyttet | Global |
a join user table / view -> catalog view / DMV | Snapshot | Skrivebeskyttet | Global |
Kredit hvor der skal krediteres – denne undersøgelse blev udløst af et svar fra Jeroen Mostert på Stack Overflow.
Så du skal være opmærksom på, at standardindstillingerne for din markør, hvis du ikke tilsidesætter dem, kan være forskellige afhængigt af den forespørgsel, der ligger til grund for markøren. Hvis du forventer en specifik adfærd i nogen eller alle tilfælde, skal du vænne dig til eksplicit at angive de muligheder, du ønsker.
Men egentlig er pointen...
…hold op med at bruge markører. Der er virkelig meget få problemer i dag, hvor den bedste løsning er en markør, især hvis du er på SQL Server 2012 eller bedre – hvor stort set alle problemer, der traditionelt løses med markører, kan løses ved hjælp af forbedringer til vinduesfunktioner. Hvis du stadig føler, at du skal bruge markører, så tag venligst rådene i dette indlæg og dets forgænger for at bestemme, hvilke muligheder du skal bruge.