sql >> Databáze >  >> RDS >> Database

Sledování možností kurzoru

Poznámka:Tento příspěvek byl původně publikován pouze v naší elektronické knize, High Performance Techniques for SQL Server, Volume 3. O našich elektronických knihách se můžete dozvědět zde.

Před více než třemi lety jsem napsal příspěvek o možnostech kurzoru na serveru SQL Server a o tom, proč byste měli přepsat výchozí hodnoty:

  • Jaký dopad mohou mít různé možnosti kurzoru?

Chtěl jsem zveřejnit následnou zprávu, abych zopakoval, že – i když byste nikdy neměli přijímat pouze výchozí hodnoty – měli byste se skutečně zamyslet nad tím, které možnosti jsou pro váš scénář nejvhodnější. Také jsem chtěl objasnit několik věcí, které se objevily v komentářích k tomuto příspěvku.

Andrew Kelly uvedl skvělou věc, a to, že STATIC kurzor vytvoří jednorázovou kopii výsledků, vloží je do databáze tempdb a poté se vyhne všem problémům se souběžností, které by mohly ovlivnit DYNAMIC kurzor. Jedna možnost není ve všech případech jasným vítězem nad druhou; můžete mít například hodně kurzorů (nebo kurzorů s velmi velkými sadami výsledků) a/nebo již přetíženou databázi tempdb a nechcete tam ukládat žádné další napětí. Ale je to něco, co stojí za to vyzkoušet.

Fabiano také uvedl skvělý bod, který je DYNAMIC a FAST_FORWARD kurzory mohou být zranitelný vůči problému Hallowe'en (diskutovaný Paulem Whitem ve 4dílné sérii, která začíná zde). Paul také poznamenal, že FAST_FORWARD nemusí být náchylné k problému, v závislosti na tom, zda optimalizátor zvolil statický nebo dynamický plán (Marc Friedman ze společnosti Microsoft se o tom podrobně věnuje zde).

Nakonec jsem chtěl poukázat na to, že ne všechny výchozí kurzory jsou vytvořeny stejně. Provedl jsem několik testů a zkontroloval, jak se SQL Server rozhodl nastavit možnosti kurzoru v různých scénářích (ověřeno pomocí sys.dm_exec_cursors funkce dynamického řízení). Kód je docela jednoduchý:

DECLARE c CURSOR FOR [...blah blah...];
SELECT properties FROM sys.dm_exec_cursors(@@SPID);

Zde jsou výsledky pro scénáře, které jsem testoval:

Dotaz kurzoru je založen na… Typ Souběh Rozsah
konstanta (FOR SELECT 1 nebo FOR SELECT SYSDATETIME() ) Snímek Pouze pro čtení Globální
tabulka #temp / ##temp Dynamické Optimistický Globální
uživatelská tabulka / pohled Dynamické Optimistický Globální
zobrazení katalogu / DMV Snímek Pouze pro čtení Globální
a join #tmp -> uživatelská tabulka / pohled Dynamické Optimistický Globální
a join #tmp -> zobrazení katalogu / DMV Snímek Pouze pro čtení Globální
připojit uživatelskou tabulku / zobrazení -> zobrazení katalogu / DMV Snímek Pouze pro čtení Globální

Kredit tam, kde je splatný kredit – toto vyšetřování vyvolala odpověď od Jeroena Mosterta na Stack Overflow.

Měli byste si tedy být vědomi toho, že výchozí možnosti pro váš kurzor, pokud je nepřepíšete, se mohou lišit v závislosti na dotazu ležícím pod kurzorem. Pokud v některém nebo všech případech očekáváte specifické chování, zvykněte si explicitně specifikovat požadované možnosti.

Ale ve skutečnosti jde o…

…přestaňte používat kurzory. Dnes je opravdu jen velmi málo problémů, kde je nejlepším řešením kurzor, zvláště pokud používáte SQL Server 2012 nebo lepší – kde téměř každý problém tradičně řešený kurzory lze vyřešit pomocí vylepšení funkcí okna. Pokud stále máte pocit, že potřebujete používat kurzory, vezměte prosím na vědomí rady v tomto příspěvku a jeho předchůdci, abyste určili, které možnosti byste měli použít.


  1. Který SQL dotaz je rychlejší? Filtrujte podle kritérií připojení nebo klauzule Where?

  2. Provádí EXCEPT rychleji než JOIN, když jsou sloupce tabulky stejné

  3. Funkce RANK, DENSE_RANK a ROW_NUMBER v Oracle

  4. Online MCQ kvíz PL/SQL