Obs! Det här inlägget publicerades ursprungligen endast i vår e-bok, High Performance Techniques for SQL Server, Volym 3. Du kan ta reda på om våra e-böcker här.
För över tre år sedan skrev jag ett inlägg om marköralternativ i SQL Server, och varför du bör åsidosätta standardinställningarna:
- Vilken effekt kan olika marköralternativ ha?
Jag ville lägga upp en uppföljning för att upprepa att – även om du aldrig bara ska acceptera standardinställningarna – bör du verkligen tänka på vilka alternativ som är mest tillämpliga på ditt scenario. Jag ville också förtydliga några saker som kom upp i kommentarerna till det inlägget.
Andrew Kelly tog upp en bra poäng, och det är en STATIC
markören gör en engångskopia av resultaten, lägger dem i tempdb och undviker sedan eventuella samtidighetsproblem som kan påverka en DYNAMIC
markören. Det ena alternativet är inte en klar vinnare över det andra i alla fall; till exempel kan du ha många markörer (eller markörer med mycket stora resultatuppsättningar) och/eller en redan överbelastad tempdb och vill inte avlasta någon ytterligare stress där. Men det är något som är värt att testa.
Fabiano tog också upp en bra poäng som både DYNAMIC
och FAST_FORWARD
markörer kan vara sårbar för Halloween-problemet (diskuterat av Paul White i en serie i fyra delar, som börjar här). Paul kommenterade också att FAST_FORWARD
kanske inte är sårbar för problemet, beroende på om optimeraren valde en statisk eller dynamisk plan (Microsofts Marc Friedman går in i detalj om det här).
Slutligen ville jag påpeka att inte alla standardmarkörer skapas lika. Jag körde några tester och kollade hur SQL Server bestämde sig för att ställa in marköralternativ under en mängd olika scenarier (validerade med sys.dm_exec_cursors
dynamisk förvaltningsfunktion). Koden är ganska enkel:
DECLARE c CURSOR FOR [...blah blah...]; SELECT properties FROM sys.dm_exec_cursors(@@SPID);
Här är resultaten för scenarierna jag testade:
Markörfrågan är baserad på... | Typ | Samtidighet | Omfattning |
---|---|---|---|
en konstant (FOR SELECT 1 eller FOR SELECT SYSDATETIME() ) | Ögonblicksbild | Skrivskyddat | Global |
en #temp / ##temp tabell | Dynamisk | Optimistisk | Global |
en användartabell/vy | Dynamisk | Optimistisk | Global |
en katalogvy / DMV | Ögonblicksbild | Skrivskyddat | Global |
a join #tmp -> användartabell/vy | Dynamisk | Optimistisk | Global |
a join #tmp -> katalogvy / DMV | Ögonblicksbild | Skrivskyddat | Global |
en gå med användartabell / visa -> katalogvy / DMV | Ögonblicksbild | Skrivskyddat | Global |
Kredit där kredit ska betalas – den här utredningen utlöstes av ett svar från Jeroen Mostert på Stack Overflow.
Så du bör vara medveten om att standardalternativen för din markör, om du inte åsidosätter dem, kan vara olika beroende på frågan som ligger bakom markören. Om du förväntar dig ett specifikt beteende i något eller alla fall, ta för vana att uttryckligen ange de alternativ du vill ha.
Men egentligen är poängen...
…sluta använda markörer. Det finns verkligen väldigt få problem idag där den bästa lösningen är en markör, speciellt om du använder SQL Server 2012 eller bättre – där nästan alla problem som traditionellt löses med markörer kan lösas med hjälp av förbättringar av fönsterfunktioner. Om du fortfarande känner att du behöver använda markörer, vänligen ta råden i det här inlägget och dess föregångare för att avgöra vilka alternativ du ska använda.