Domanda

Ho una procedura memorizzata che richiede un secondo per eseguire normalmente. Gli utenti desideravano dati da un'altra tabella in quella query, quindi ho unito che i dati con un sindacato tutti e un grappolo di colonne fittizie mancanti nella nuova tabella.

Ha funzionato bene nei test, ma quando ci ha distribuito su un server SQL 2000, ha iniziato a ottenere timeout. La vecchia query viene eseguita sotto un secondo, e le 2 nuove query sono entrambe entrambe in secondo luogo, ma quando sono combinate usando unione tutto, i tempi di query fuori.

Ecco l'idea generale di come appare la query. La query reale ha circa 20 parametri di input e restituisce circa 30 o 40 colonne, ma questo dovrebbe dare l'idea di base:

CREATE PROCEDURE dbo.SearchHistory
(
    @Criteria1 bigint,
    @Criteria2 int,
    @Criteria3 varchar(10)
)
AS
BEGIN
    -- Part 1
    SELECT
        A,
        NULL AS B,
        0 AS C,
        D
    FROM TableA
    WHERE @Criteria1 IS NULL
    AND @Criteria3 IS NULL
    AND (A = @Criteria2 OR @Criteria2 IS NULL)

UNION ALL

    -- Part 2
    SELECT
        A,
        NULL AS B,
        0 AS C,
        E
    FROM TableA
    WHERE @Criteria1 IS NULL
    AND @Criteria3 IS NULL
    AND (A = @Criteria2 OR @Criteria2 IS NULL)

UNION ALL

    -- Part 3
    SELECT
        A,
        B,
        C,
        D
    FROM TableB
    WHERE (F = @Criteria1 OR @Criteria1 IS NULL)
    AND (A = @Criteria2 OR @Criteria2 IS NULL)
    AND (G = @Criteria3 OR @Criteria3 IS NULL)
END
.

Nell'esempio precedente, @ criterio1 non è null, quindi parte 1 e 2 restituiranno 0 righe e la parte 3 restituisce solo 3 righe. Ma se commendo la parte 1 e 2, termina immediatamente; Se li lascio, ottengo un timeout.

Come si convince il server SQL a non scherzare con il suo piano di esecuzione in una situazione come questa?

È stato utile?

Soluzione

I think your problem is because of SQL Server's parameter sniffing.

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx

I have come across it a good few times. There are a few ways around it. E.g. use WITH RECOMPILE as @Biff MaGriff suggested. The easiest way I found to fix is to convert all your input parameters to local parameters, and use the local ones.

Altri suggerimenti

This cannot be answered without seeing the execution plans (please post them as images, one for each part and one for the union query). A workaround is to use a temp table in which you insert the the parts separately. A better solution however would be to fix the query in the first place.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top