Questo è ciò che ho imparato finora dalla mia ricerca.
.NET invia impostazioni di connessione che non sono le stesse che ottieni quando accedi a Management Studio. Ecco cosa vedi se annusi la connessione con Sql Profiler:
-- network protocol: TCP/IP
set quoted_identifier off
set arithabort off
set numeric_roundabort off
set ansi_warnings on
set ansi_padding on
set ansi_nulls off
set concat_null_yields_null on
set cursor_close_on_commit off
set implicit_transactions off
set language us_english
set dateformat mdy
set datefirst 7
set transaction isolation level read committed
Ora sto incollando quelle impostazioni sopra ogni query che eseguo quando accedo al server sql, per assicurarmi che le impostazioni siano le stesse.
In questo caso, ho provato ciascuna impostazione individualmente, dopo essermi disconnesso e ricollegato, e ho scoperto che la modifica di arithabort da off a on ha ridotto la query del problema da 90 secondi a 1 secondo.
La spiegazione più probabile è correlata allo sniffing dei parametri, che è una tecnica utilizzata da SQL Server per scegliere quello che ritiene sia il piano di query più efficace. Quando modifichi una delle impostazioni di connessione, Query Optimizer potrebbe scegliere un piano diverso e, in questo caso, a quanto pare ne ha scelto uno errato.
Ma non ne sono del tutto convinto. Ho provato a confrontare i piani di query effettivi dopo aver modificato questa impostazione e devo ancora vedere le differenze mostrare eventuali modifiche.
C'è qualcos'altro nell'impostazione di arithabort che potrebbe causare l'esecuzione lenta di una query in alcuni casi?
La soluzione sembrava semplice:basta mettere set arithabort nella parte superiore della procedura memorizzata. Ma questo potrebbe portare al problema opposto:modificare i parametri della query e improvvisamente funziona più velocemente con "off" che "on".
Per il momento sto eseguendo la procedura "con ricompilazione" per assicurarmi che il piano venga rigenerato ogni volta. Va bene per questo particolare rapporto, dal momento che ci vuole forse un secondo per ricompilare, e questo non è troppo evidente su un rapporto che impiega 1-10 secondi per tornare (è un mostro).
Ma non è un'opzione per altre query che vengono eseguite molto più frequentemente e devono essere restituite il più rapidamente possibile, in pochi millisecondi.