none
Possibili soluzioni per query con output composto da molti record RRS feed

  • Domanda

  • Ciao a tutti, sto riscontrando un problema ,e cioè la pesantezza di una query

     

    "select distinct ROW_NUMBER()over (order by nome) as 'Numero',nome from tabella"
    
    
    
    
    

     

    contenuta in una stored procedure su sql server express 2008

    Detto cio'la query tira fuori 10000 record  ,e la sua esecuzione dura diversi secondi prima di fornire l output

    Ora le domande

    1) posso dividere il risultato della query in piu' "blocchi" ?

    2) su sql server ho notato che il dbms comincia a scrivere i risultati e contemporaneamente,la query calcola i successivi (ma fa visualizzare quelli appena calcolati!) , mentre è come se su vb.net prima calcolasse tutto e poi aggiornasse il mio datagridview...c è un modo per fargli assumere lo stesso comportamento?

    Vi ringrazio

    mercoledì 26 maggio 2010 15:02

Risposte

  • Non carichi tutti i datoi in memoria. Se li carichi tutti in memoria sprechi spazio, la griglia ci mette sempre tanto tempo e l'utente smette di utilizzare il tuo programma dopo dieci minuti perchè una tabella da 10000 record non è utilizzabile.

    Dovresti visualizzare i dati in pagine. Per fare questo devi preventivamente sapere quanti record ci sono e per fare ciò fai una select count.
    Una volta noti quanti record ci sono sai quante pagine ci saranno dividendo il numero di record per la dimensione (come numero di record) per ogni pagina. A questo punto, supponendo che le pagine siano composte da n record, le pagine sono recuperabili con la query:

    SELECT Numero, nome
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Nome]) AS Numero, Nome
        FROM [dbo].[Tabella] AS [t0]
        ) AS [t1]
    WHERE [t1].numero BETWEEN nPage*n AND (nPage+1)*n-1

    dove nPage è il numero di pagina (prima pagina nPage=0).

    A questo punto visualizzi solo i record recuperati in quewsto modo ottenendo un accesso rapido e una griglia più leggibile.

    Per quanto riguarda gli indici prima leggiti http://it.wikipedia.org/wiki/Indice_(database). Si tratta, in sostanza, di strutture della banca dati che ottimizzano le ricerche. Quando metti un indice su un campo è come se avessi un'altra tabella ordinata in base al campo su cui hai messo l'indice. Questo significa che se fai una ricerca su tale campo il database esegue una ricerca binaria anzichè eseguire una scansione della tabella minimizzando i tempi.

    • Contrassegnato come risposta NikkySixx giovedì 27 maggio 2010 18:32
    giovedì 27 maggio 2010 18:20
    Moderatore

Tutte le risposte

  • Ciao,
     
    Alla domanda 1 la risposta è si, alla domanda 2 la risposta è una
    domanda: come carichi i dati da Sql Server?
     
    ..m
     
     
     

    Mauro Servienti
    {C67C0157-5D98-4733-A75E-93CAEE4BADC8}
    Microsoft MVP - Visual C# / MCP
    http://mvp.support.microsoft.com
    http://blogs.ugidotnet.org/topics
    whynot [ at ] topics [ dot ] it
    mercoledì 26 maggio 2010 17:16
  • Ciao! per quanto riguarda la prima domanda,pero' è come se ti avessi chiesto l ora,e tu mi avessi risposto affermativamente e te ne fossi andato :D

    Scherzi a parte,come si fa?

    Per il secondo quesito,devo dire che la differenza usando una stored è sensibile,rispetto al richiamarla dal client,ma ho il terrore che quei 5 secondi diventaranno molti di piu'all aumentare dei record...e sopratutto non ha alcun senso restituire all utente oltre 10000 record,per questo volevo dividere i risultati in piu'tabelle

    I dati vengono caricati da sql server,attraverso un data adapter,che riempe una tabella del mio dataset ,che a sua volta riversa i dati nel datagridview....mi piacerebbe riuscire a "imitare" il comportamento di sql server nel restituire i risultati (cioè cominciare a riempire la tabella output,prima che la query sia arrivata a conclusione) ma forse è solo una mia fantasia :)

    Grazie!

     

    mercoledì 26 maggio 2010 18:20
  • La query che puoi utilizzare per recuperare un "pacchetto" di dati potrebbe essere la seguente:

     SELECT Numero, nome
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Nome]) AS Numero, Nome
        FROM [dbo].[Tabella] AS [t0]
        ) AS [t1]
    WHERE [t1].numero BETWEEN 100 AND 1000

    Tiu consiglierei di mettere un indice sul campo Nome.

    Ho creato una tabella sul mio sql con 1000000 records e la precedente (con indice) è quasi immediata.

    mercoledì 26 maggio 2010 20:50
    Moderatore
  • Ciao,
     
    la "suddivisione in blocchi" si chiama paginazione, nn c'è nulla di
    pronto per farla ma farsela è abbastanza banale, devi tenere traccia di
    quanti record vuoi per pagina e di che pagina ti interessa.
     
    Pe ril esto il problema è evidente stai usando un DataSet/DataTable
    qundi stai caricando tutti i record in memoria per poi solo dopo
    usarli, se vuoi avere un compotamento simile a quello di Management
    Studio devi scendere ad un livello più basso e ad esempio caricare i
    dati con un DataReader e smazzarti un po' di problemini.
     
    ..m
     
     
     

    Mauro Servienti
    {C67C0157-5D98-4733-A75E-93CAEE4BADC8}
    Microsoft MVP - Visual C# / MCP
    http://mvp.support.microsoft.com
    http://blogs.ugidotnet.org/topics
    whynot [ at ] topics [ dot ] it
    giovedì 27 maggio 2010 04:37
  • @Massimo Bonanni: mi sembra un ottima soluzione,ma ho un paio di dubbi, in pratica dovrei fare qualcosa del genere

    Avevo pensato a fare un for di select finchè  non raggiungo il limite della tabella...è corretto?

    I dati cosi ottenuti pero'andrebbero messi in tabelle temporanee?o in nuove tabelle? in entrambi i casi su questo punto non saprei come procedere

    Il secondo dubbio riguarda gli indici,ho letto un po di informazioni,ma molto frammentate e ne conosco poco sia i concetti che l utilizzo pratico.Puoi darmi qualche dritta?

    Grazie ^_^

    giovedì 27 maggio 2010 10:45
  • Non carichi tutti i datoi in memoria. Se li carichi tutti in memoria sprechi spazio, la griglia ci mette sempre tanto tempo e l'utente smette di utilizzare il tuo programma dopo dieci minuti perchè una tabella da 10000 record non è utilizzabile.

    Dovresti visualizzare i dati in pagine. Per fare questo devi preventivamente sapere quanti record ci sono e per fare ciò fai una select count.
    Una volta noti quanti record ci sono sai quante pagine ci saranno dividendo il numero di record per la dimensione (come numero di record) per ogni pagina. A questo punto, supponendo che le pagine siano composte da n record, le pagine sono recuperabili con la query:

    SELECT Numero, nome
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[Nome]) AS Numero, Nome
        FROM [dbo].[Tabella] AS [t0]
        ) AS [t1]
    WHERE [t1].numero BETWEEN nPage*n AND (nPage+1)*n-1

    dove nPage è il numero di pagina (prima pagina nPage=0).

    A questo punto visualizzi solo i record recuperati in quewsto modo ottenendo un accesso rapido e una griglia più leggibile.

    Per quanto riguarda gli indici prima leggiti http://it.wikipedia.org/wiki/Indice_(database). Si tratta, in sostanza, di strutture della banca dati che ottimizzano le ricerche. Quando metti un indice su un campo è come se avessi un'altra tabella ordinata in base al campo su cui hai messo l'indice. Questo significa che se fai una ricerca su tale campo il database esegue una ricerca binaria anzichè eseguire una scansione della tabella minimizzando i tempi.

    • Contrassegnato come risposta NikkySixx giovedì 27 maggio 2010 18:32
    giovedì 27 maggio 2010 18:20
    Moderatore
  • Ok ,come sempre ,ti ringrazio di tutto ;)
    giovedì 27 maggio 2010 18:32