in

UGISS Community

Il sito della community dello User Group Italiano di SQL Server

rowcount e top

Last post 04-28-2009 12.18 by giacomo23. 5 replies.
Page 1 of 1 (6 items)
Sort Posts: Previous Next
  • 04-24-2009 19.17

    rowcount e top

    Ciao, 

    Ho bisogno di conoscere il numero totale di record che risultano da un certo filtro, e poi di eseguire la stessa select con TOP (@n). Questo per permettere alla pagina web di dividere i record in pagine separate. Quello che faccio adesso banalmente è eseguire prima un

    select count(*) from T where [condizioni di filtro]

    e poi

     select Top (@n) * from T where [condizioni di filtro] 

    E' possibile fare tutto in un'unica operazione risparmiandomi una select?

     

    Giacomo

    • Post Points: 20
  • 04-25-2009 17.20 In reply to

    • dmauri
    • Top 10 Contributor
      Male
    • Joined on 05-14-2007
    • Novate Milanese
    • Posts 1.907
    • Points 24.955

    Re: rowcount e top

    giacomo23:
    E' possibile fare tutto in un'unica operazione risparmiandomi una select?

    No, dato che nella prima query richiedi che venga fatto il conto di tutte le righe, mentre nella seconda limiti il numero di righe da restituire con l'operatore TOP e quindi SQL Server non ha nessun bisogno di leggersti tutte le righe (se c'è un indice corretto), ma si può limitare a leggere solo quelle richieste.

    Se la domanda mira a risolvere un problema di performance, direi che la cosa da fare è semplicemente controllare che la clausola where sia scritta in modo da utilizzare gli indici che ci sono. Se non ce ne sono, valutane la creazione Smile

    http://www.ugiss.org/Content/Article/SQL-Server-2005-implementazione-di-indici-efficaci.aspx

     

    Davide Mauri
    Microsoft MVP - SQL Server, MCP, MCAD, MCDBA, MCT - http://www.davidemauri.it
    Socio Fondatore e Mentor di Solid Quality Learning Italy - http://www.solidq.com
    Presidente di UGISS: User Group Italiano Sql Server - http://www.ugiss.org
    • Post Points: 20
  • 04-26-2009 11.24 In reply to

    Re: rowcount e top

    Ciao Davide, grazie per la risposta. 

    Spiego meglio la mia necessità. I filtri di ricerca vengono impostati dall'utente, per cui è possibile che filtri non ottimali restituiscano un numero di record troppo elevato. Per ricavare il numero di record restituiti dalla query  ho sempre bisogno di eseguire il count(*), e in base al numero di record restituiti decido se lanciare anche la select * per restiruire i dati oppure restituire alla pagina web un messaggio che chiede di eseguire una ricerca piu' selettiva.

    Secondo te, in termini di prestazioni è meglio usare questo metodo ( eseguo sempre count (*) e poi select * solo se il rowcount < limite) oppure è piu' vantaggioso eseguire sempre select * into #T ? Utilizzare tabelle temporanee mi sembra eccessivamente pesante, soprattutto se il filtro è mal costruito e i record restituiti sono molti. D'altra parte potrei limitare sempre il risultato ad un limite prefissato (ad es 2000 record). Cosa mi consigli di fare?

    Ciao

     

    Giacomo

    • Post Points: 35
  • 04-26-2009 13.07 In reply to

    • lucazav
    • Top 25 Contributor
      Male
    • Joined on 06-04-2007
    • Lodi (LO)
    • Posts 92
    • Points 1.000

    Re: rowcount e top

     Ciao Giacomo Smile

    mi permetto di intromettermi nella discussione tra te e Davide per condividere con voi quella che è stata la mia soluzione ad un problema similare.
    Trovandomi anch'io di fronte a query che restituivano migliaia di risultati da visualizzare in base a filtri impostati dall'utente, ho ritenuto opportuno adottare la strategia che va sotto il nome di "Paginazione lato server". Innanzi tutto, dal principio ho deciso che il Data Layer dell'applicazione dovesse risiedere nel server, realizzato tramite Stored Procedure (già compilate, quindi più performanti). Di conseguenza, nelle query che restituivano gli item da paginare nell'applicativo Web ho introdotto una serie di parametri che servivano a limitare gli item restituiti in base alla pagina richiesta dall'utente tramite il client. In particolare, ho usato questi parametri:

    • itemsPerPage: numero massimo di item che il client può visualizzare in una pagina. Se il recordset calcolato dalla SP ha un numero di item maggiore di itemPerPage, la SP restituirà solo una pagina contenente un numero di item pari a itemPerPage (personalmente, ho dichiarato la variabile itemPerPage globalmente)

    • startItem: l'indice del primo item che la SP dovrà restituire. Quando, per esempio, l'utente visiterà la seconda pagina degli item da lui precedentemente filtrati, e supponendo che itemsPerPage sia 10, la SP avrà in ingresso un valore di startItem pari a 11, e dunque dovrà restituire gli item che vanno dall'11-mo al 20-mo (qui trovi come realizzare la paginazione in T-SQL con o senza CTE)

    In questo modo, a prescindere dal filtro utilizzato dall'utente, la SP restituirà sempre un numero di item pari a itemsPerPage. Inoltre, il numero di pagine totale dei dati richiesti dall'utente ( Math.Ceiling(itemsTotalNum / itemsPerPage) ), variabile a seconda dei filtri impostati e necessario per generare sul client i link alle pagine da visitare (page navigator), verrà memorizzato nella sessione corrente, in modo da non eseguire più di una volta la query che lo calcola, ottimizzando così le prestazioni.
    Nel Business Layer si utilizzerà il numero di pagina da visualizzare scelto dall'utente e il numero di item per pagina, in modo da calcolare lo startItem che servirà alla SP. Infatti, dato il numero di pagina da visualizzare (pageNum) e il numero di item per pagina (itemsPerPage) si ha che:

    startItem = (pageNum - 1) * itemsPerPage

    valore che possiamo a questo punto passare alla nostra SP Smile

     

    Non so se si tratta della soluzione migliore, è semplicemente un'alternativa alla soluzione da te intrapresa.
    Ciao!

    Luca Zavarella
    Data Platform Specialist - SolidQ Italia
    Business Intelligence MCTS & MCITP
    Blog: http://community.ugiss.org/blogs/lucazav
    • Post Points: 5
  • 04-26-2009 13.54 In reply to

    • dmauri
    • Top 10 Contributor
      Male
    • Joined on 05-14-2007
    • Novate Milanese
    • Posts 1.907
    • Points 24.955

    Re: rowcount e top

    giacomo23:
    D'altra parte potrei limitare sempre il risultato ad un limite prefissato (ad es 2000 record).

    Io sono per questa strada Smile

    L'idea è quella di poter mettere un limite massimo alle righe restituite, e quindi paginare queste. E' empiricamente provato che nessun utente va mai dopo la 5a pagina...chiaramente la tua applicazione potrebbe avvisare l'utente che ha messo dei filtri troppo poco selettivi, quindi la quantità di risultati è stata limitata a 2000 (ad es.)

     

    Davide Mauri
    Microsoft MVP - SQL Server, MCP, MCAD, MCDBA, MCT - http://www.davidemauri.it
    Socio Fondatore e Mentor di Solid Quality Learning Italy - http://www.solidq.com
    Presidente di UGISS: User Group Italiano Sql Server - http://www.ugiss.org
    • Post Points: 20
  • 04-28-2009 12.18 In reply to

    Re: rowcount e top

    La soluzione che adottero' è questa. Peccato pero' che non esista una opzione top che restituisca anche il numero di record completo... una specie di top percent, che fa esattamente la stessa cosa per calcolare la percentuale richiesta ( e che comunque è molto lento).

     

    Ciao e grazie a tutti

     

    Giacomo

    • Post Points: 5
Page 1 of 1 (6 items)
(C) 2007 User Group Italiano di SQL Server