Condividi tramite


Problemi relativi alle prestazioni di T-SQL

Si applica a: SQL Server database SQL di Azure Istanza gestita di SQL di Azure database SQL in Microsoft Fabric

Quando si analizza il codice T-SQL nel progetto di database, uno o più avvisi potrebbero essere classificati come problemi di prestazioni. È consigliabile risolvere un problema di prestazioni per evitare la situazione seguente:

  • Un'analisi di tabella viene eseguita quando viene eseguito il codice.

In generale, è possibile eliminare un problema di prestazioni se la tabella contiene dati così piccoli che un'analisi non causerà un calo significativo delle prestazioni.

Le regole fornite identificano i problemi di prestazioni seguenti:

SR0004: evitare di usare colonne che non dispongono di indici come espressioni di test nei predicati IN

Se si usa una clausola WHERE che fa riferimento a una o più colonne non indicizzate come parte di un predicato IN, si verifica un'analisi di tabella. L'analisi della tabella riduce le prestazioni.

Come correggere le violazioni

Per risolvere questo errore, apportare una delle modifiche seguenti:

  • Modificare il predicato IN in modo che faccia riferimento solo alle colonne con un indice.
  • Aggiungere un indice a qualsiasi colonna a cui fa riferimento il predicato IN e che non dispone già di un indice.

Esempio

In questo esempio, una semplice istruzione SELECT fa riferimento a una colonna [c1], che non ha un indice. La seconda istruzione definisce un indice che è possibile aggiungere per risolvere questo avviso.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
AS
SELECT [Comment]
FROM [dbo].[Table2]
WHERE [c1] IN (1, 2, 3)

CREATE INDEX [IX_Table2_C1]
ON [dbo].[Table2] (c1);

SR0005: evitare di usare modelli che iniziano con "%" nei predicati LIKE

È possibile che un'analisi di tabella venga eseguita se si usa una clausola WHERE contenente un predicato LIKE, ad esempio '%pattern string' per cercare testo che può verificarsi in qualsiasi punto di una colonna.

Come correggere le violazioni

Per risolvere questo problema, è necessario modificare la stringa di ricerca in modo che inizi con un carattere che non sia un carattere jolly (%), oppure è necessario creare un indice full-text.

Esempio

Nel primo esempio l'istruzione SELECT genera un'analisi di tabella perché la stringa di ricerca inizia con un carattere jolly. Nel secondo esempio, l'istruzione genera una ricerca di indice perché la stringa di ricerca non inizia con un carattere jolly. Una ricerca di indice recupera solo le righe che corrispondono alla clausola WHERE.

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE '%pples'

SELECT [dbo].[Table2].[ID], [dbo].[Table2].[c1], [dbo].[Table2].[c2], [dbo].[Table2].[c3], [dbo].[Table2].[Comment]
FROM dbo.[Table2]
WHERE Comment LIKE 'A%'

SR0006: spostare un riferimento di colonna a un lato di un operatore di confronto per usare un indice di colonna

Il codice potrebbe causare un'analisi di tabella se confronta un'espressione che contiene un riferimento a una colonna.

Come correggere le violazioni

Per risolvere questo problema, è necessario rielaborare il confronto in modo che il riferimento alla colonna venga visualizzato da solo su un lato dell'operatore di confronto, anziché all'interno di un'espressione. Quando si esegue il codice con il riferimento di colonna da solo su un lato dell'operatore di confronto, SQL Server può usare l'indice di colonna e non viene eseguita alcuna analisi di tabella.

Esempio

Nella prima procedura, una clausola WHERE include la colonna [c1] in un'espressione come parte di un confronto. Nella seconda procedura i risultati del confronto sono identici ma non richiedono mai un'analisi di tabella.

CREATE PROCEDURE [dbo].[Procedure3WithWarnings]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] + 5 > @param1)

CREATE PROCEDURE [dbo].[Procedure3Fixed]
@param1 int
AS
SELECT [c1], [c2], [c3], [Comment]
FROM [dbo].[Table2]
WHERE ([c1] > (@param1 - 5))

SR0007: usare ISNULL(column, default_value) in colonne che ammette i valori nulli nelle espressioni

Se il codice confronta due valori NULL o un valore NULL con qualsiasi altro valore, il codice restituisce un risultato sconosciuto.

Come correggere le violazioni

È consigliabile indicare in modo esplicito come gestire i valori NULL nelle espressioni di confronto eseguendo il ritorno a capo di ogni colonna che può contenere un valore NULL in una funzione ISNULL.

Esempio

In questo esempio viene illustrata una definizione di tabella semplice e due stored procedure. La tabella contiene una colonna, c2, che può contenere un valore NULL. La prima routine, ProcedureWithWarning, confronta c2 con un valore costante. La seconda procedura risolve il problema eseguendo il ritorno a capo c2 con una chiamata alla funzione ISNULL.

CREATE TABLE [dbo].[Table1]
(
[ID] INT NOT NULL IDENTITY(0, 1),
[c1] INT NOT NULL PRIMARY KEY,
[c2] INT
)
ON [PRIMARY]

CREATE PROCEDURE [dbo].[ProcedureWithWarning]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
 WHERE [c2] > 2;
END

CREATE PROCEDURE [dbo].[ProcedureFixed]
AS
BEGIN
SELECT COUNT(*) FROM [dbo].[Table1]
WHERE ISNULL([c2],0) > 2;
END

SR0015: estrarre chiamate di funzione deterministiche dai predicati WHERE

In un predicato WHERE, una chiamata di funzione è deterministica se il relativo valore non dipende dai dati selezionati. Tali chiamate potrebbero causare analisi di tabelle non necessarie, riducendo le prestazioni del database.

Come correggere le violazioni

Per risolvere questo problema, è possibile assegnare il risultato della chiamata a una variabile usata nel predicato WHERE.

Esempio

Nel primo esempio la stored procedure include una chiamata di funzione deterministica, ABS(@param1), nel predicato WHERE. Nel secondo esempio una variabile temporanea contiene il risultato della chiamata.

CREATE PROCEDURE [dbo].[Procedure2WithWarning]
@param1 INT = 0,
AS
BEGIN
SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > ABS(@param1)
END

CREATE PROCEDURE [dbo].[Procedure2Fixed]
@param1 INT = 0,
AS
BEGIN
DECLARE @AbsOfParam1 INT
SET @AbsOfParam1 = ABS(@param1)

SELECT [c1], [c2], [c3], [SmallString]
FROM [dbo].[Table1]
WHERE [c2] > @AbsOfParam1
END