none
Prestazioni query con parametri RRS feed

  • Discussione generale

  • Buongiorno a tutti.

    Scusate... ma proprio non riesco ad andare avanti.

    Sarò lapidario:

    Ho una query che rallenta parecchio le prestazioni di un'applicazione web.

    Dopo aver isolato tutte le possibili cause mi sono accorto che:

    select  top(60) * from vw_usersdocs(@iduser) where  iddoc not in (SELECT idattach from reg_attachs where iddoc =68597)  and   IDCL = @idcl

    Dove @idcl è valorizzato a 17 , Restituisce 60 risultati in meno di 1 secondo. 

    select  top(60) * from vw_usersdocs(@iduser) where iddoc not in (SELECT idattach from reg_attachs where iddoc =68597)  and   IDCL = 17

    Restituisce lo stesso set di risultati in ben più di 3 secondi.

    Entrambe le query sono lanciate direttamente in SQL Management Studui Express.

    Dico io... la query è la stessa. Come mai??


    lunedì 26 novembre 2012 14:49

Tutte le risposte

  • I parametri nella migliore delle ipotesi fanno una patta :) di solito rallentano rispetto a una stringa. La mia palla di vetro dice che ti stai scontrando con la cache...

    Comunque l'excution plan è ciò da cui devi partire; dovrebbe essere identico. p.s. iduser è sempre uguale giusto?

    lunedì 26 novembre 2012 15:20
  • Ti ringrazio per la risposta.

    Faccio difficoltà a credere che sia un problema di cache.

    Le due query sono lanciate dallo stesso ambiente (SMSE) più volte di seguito, anche consecutivamente una rispetto all'altra e sempre con lo stesso risultato: 0sec la prima 3sec la seconda.

    @iduser è valorizzato in modo identico. Immediatamente prima della query ho:

    declare @idcl int;
    declare @iduser int;
     set @iduser = 2;
    set @idcl =17;

    Infine ti confesso che faccio difficoltà ad interpretrare il piano d'esecuzione stimato. :-(

    lunedì 26 novembre 2012 15:36
  • mspaint o SET SHOWPLAN_TEXT ON e vedi cosa riesci a postare senza "allagare"...

    azzerare la cache è un attimo... metti che x qualche ragione quella da 3sec sia sempre ricalcolato il plan.

    sicuro sia tutto uguale uguale?

    e mi preoccupo, la TOP 60 lavora prima o dopo (come credo) della funzione?

    insomma non so che dirti :)

    lunedì 26 novembre 2012 16:10
  • Cache azzerata. Niente. Il costo effettivo delle due query è differente di circa 2800 millisecondi.

    Ho isolato ulteriormente la query, eliminando clausole top e risalendo alla funzione radice.

    Occhio:

    ------------------------------------------

     declare @idcl int;
     set @idcl=17;
     
    SELECT     DOCS.IDDoc, DOCS.IDCL, DOCS.Documento, DOCS.inserted, DOCS.Num, DOCS.IDOwner,
                           (SELECT     COUNT(*)
                                FROM          REG_ATTACHS
                                WHERE      ( REG_ATTACHS.IDDoc = DOCS.IDDoc)) AS ATTACHS,    fUserDocs_1.Code, fUserDocs_1.CanRead, CLS.Classe
    FROM         dbo.fUserDocs(5) AS fUserDocs_1 INNER JOIN
                          DOCS ON fUserDocs_1.iddoc = DOCS.IDDoc LEFT OUTER JOIN
                          CLS ON DOCS.IDCL = CLS.IDCL
    WHERE   cls.IDCL =@idcl;    

    --------------------------------------------

    Lascia perdere i dettagli della query... vai alla fine.

    Incredible ma vero... se sostituisco @idcl con 17... ho un incremento di 3 secondi.

    Dico... non è possibile... ma è un fatto.

    Dettaglio: IDCL è una classe documentale. Il filtro sulla classe 17 restituisce un set di poco più di 7000 risultati sulla query in oggetto. La cosa si verifica 'solo con la classe 17. Altre classi restituiscono set di risultati ben maggiori (16.000, 30.000 ) ... praticamente istantaneamente.

    Capisco che si possa rispondere: "Non conosciamo i dettagli di implementazione delle tue funzioni o delle viste coinvolte... quindi impossibile darti una mano".

    Amen.

    Ma qui stiamo parlando di sostituire NELLA STESSA IDENTICA QUERY un numero (17) con un parametro (@idcl) valorizzato con lo stesso numero.

    lunedì 26 novembre 2012 17:25
  • deve cambiare per forza l'execution plan! Mi spiace, ma non so proprio cosa possa essere

    (prova a "isolare" ancora... togliendo la funzione?)

    martedì 27 novembre 2012 09:40
  • deve cambiare per forza l'execution plan! 

    Ciao a tutti,

    @Fabio T, postaci il piano di esecuzione delle due query (con e senza numero) almeno proviamo ad aiutarti.

    Così non è facile capire, ogni realtà va contestualizzata :)


    Alessandro Alpi SQL Server MVP

    martedì 4 dicembre 2012 09:13
    Moderatore
  • Una cosa potrebbe cambiare in termini di prestazioni.. la query con la variabile @idcl viene lanciata dentro una stored mentre la stessa query con valore IDCL = 17 la stai eseguendo da un foglio di query? In quel caso, il foglio di query è sempre piu lento della stored lanciata..

    (:

    giovedì 6 dicembre 2012 13:11
  • Ciao, 

    allora premetto che gestire i parametri è in linea di massima è SEMPRE preferibile, per una serie di ragioni:

    - La prima è quella della sicurezza, per evitare l'SQL Injection. E' chiaro che se il tuo parametro è un intero è difficile incorrere in questo problema.

    - La seconda ragione è proprio quella delle performances (può sembrare strano ma è così). Passando infatti parametri ad una query dai la POSSIBIILITA' a SQL server di compilare la query una volta solamente, e di ri-utilizzare il piano di esecuzione. Calcolare il piano di esecuzione ha un costo proporzionale alla complessità della tua stored procedure/query/prepared statement. Ricordo cmq che SQL Server sopratttutto nelle versioni più evolute (Recenti e/o enterprise) è in grado di capire se c'è un parametro dove tu metti una costante se esegui più volte la stessa query con costanti differenti (in sostanza le parametrizza da solo).

    Ora, proprio il piano di esecuzione calcolato è la ragione dei tuoi problemi. La query con parametro è ottimizzata affinchè le performances siano MEDIAMENTE migliori, rispetto al tuo database specifico (statistiche sulla distribuzione dei dati sulle tabelle coninvolte, i join - compresi quelli della funzione che chiami, ... e gli indici a disposizione).

    La soluzione non può prescindere da un'attenta analisi del piano di esecuzione, che puoi generare premendo l'apposita icona "Include Execution Plan" sul Query Analyzer (o SQL Management Studio).

    HTH,
    Ciao


    Adriano

    martedì 11 dicembre 2012 08:16