Database
 sql >> Database >  >> RDS >> Database

Follow-up sulle opzioni del cursore

Nota:questo post è stato originariamente pubblicato solo nel nostro eBook, High Performance Techniques for SQL Server, Volume 3. Puoi trovare informazioni sui nostri eBook qui.

Più di tre anni fa, ho scritto un post sulle opzioni del cursore in SQL Server e sul perché dovresti sovrascrivere le impostazioni predefinite:

  • Che impatto possono avere le diverse opzioni del cursore?

Volevo pubblicare un seguito per ribadire che, anche se non dovresti mai semplicemente accettare le impostazioni predefinite, dovresti davvero pensare a quali opzioni sono più applicabili al tuo scenario. Volevo anche chiarire alcuni elementi emersi nei commenti a quel post.

Andrew Kelly ha sollevato un ottimo punto, ovvero che è un STATIC cursore esegue una copia unica dei risultati, li inserisce in tempdb e quindi evita eventuali problemi di concorrenza che potrebbero influire su un DYNAMIC cursore. Un'opzione non è un chiaro vincitore rispetto all'altra in tutti i casi; ad esempio, potresti avere molti cursori (o cursori con set di risultati molto grandi) e/o un tempdb già sovraccaricato e non vuoi scaricare alcun ulteriore stress lì. Ma è qualcosa degno di essere testato.

Fabiano ha anche sollevato un ottimo punto che sia DYNAMIC e FAST_FORWARD i cursori possono essere vulnerabile al problema di Halloween (discusso da Paul White in una serie in 4 parti, a partire da qui). Paul ha anche commentato che FAST_FORWARD potrebbe non essere vulnerabile al problema, a seconda che l'ottimizzatore abbia scelto un piano statico o dinamico (Marc Friedman di Microsoft ne approfondisce i dettagli qui).

Infine, volevo sottolineare che non tutti i cursori predefiniti sono creati uguali. Ho eseguito alcuni test e verificato come SQL Server ha deciso di impostare le opzioni del cursore in una varietà di scenari (convalidato utilizzando sys.dm_exec_cursors funzione di gestione dinamica). Il codice è piuttosto semplice:

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

Ecco i risultati per gli scenari che ho testato:

La query del cursore si basa su... Tipo Concorrenza Ambito
una costante (FOR SELECT 1 o FOR SELECT SYSDATETIME() ) Istantanea Sola lettura Globale
una tabella #temp / ##temp Dinamico Ottimista Globale
una tabella/vista utente Dinamico Ottimista Globale
una vista catalogo / DMV Istantanea Sola lettura Globale
un join #tmp -> tabella/vista utente Dinamico Ottimista Globale
a join #tmp -> vista catalogo / DMV Istantanea Sola lettura Globale
una tabella/vista utente di join -> vista catalogo/DMV Istantanea Sola lettura Globale

Credito dove è dovuto il credito:questa indagine è stata avviata da una risposta di Jeroen Mostert su Stack Overflow.

Quindi dovresti essere consapevole del fatto che le opzioni predefinite per il tuo cursore, se non le sostituisci, potrebbero essere diverse a seconda della query alla base del cursore. Se ti aspetti un comportamento specifico in uno o in tutti i casi, prendi l'abitudine di specificare esplicitamente le opzioni che desideri.

Ma in realtà, il punto è...

...smetti di usare i cursori. Ci sono davvero pochissimi problemi oggi in cui la soluzione migliore è un cursore, soprattutto se si utilizza SQL Server 2012 o superiore, in cui quasi tutti i problemi tradizionalmente risolti dai cursori possono essere risolti utilizzando miglioramenti alle funzioni della finestra. Se ritieni ancora di dover utilizzare i cursori, segui i consigli in questo post e nel suo predecessore per determinare quali opzioni dovresti utilizzare.