Newsgroup: it.comp.www.asp
Titolo: Paginazione ADO e rallentamento su SQL server

Ciao a tutti,
premetto che non sono espertissimo su ASP, uso abitualmente PHP+MySQL
ma sto sviluppando un gestionale in ASP+SQL server.
Sql server non supporta una clausola LIMIT tipo quella di MySQL o
PostgreSQL che mi permette di selezionare, ad es. solo i record dal
50esimo al 100esimo.
Per effettuare la classica "paginazione" si ricorre quindi ad ADO; con
la conseguenza che ogni volta che mi devo vedere 10 record la mia
query iniziale me ne restituisce migliaia (tutti i record della
tabella) e dopo vengono isolati quelli che mi interessano.
Ora: questo modo di procedere, unito al fatto che devo eseguire query
piuttosto complesse (join su piu' tabelle) mi provoca un decadimento
delle prestazioni notevole. Gia' con una tabella di 20000 record i
tempi di visualizzazione dei risultati di una ricerca sono appena
accettabili.
Come vi comportate voi normalmente? Ho letto post arretrati e visto
alcuni workaround per simulare i limit anche su SQL server
(utilizzando TOP combinato con subselect) ma non riesco ad applicarli
a query complesse, con join e ordinamenti.
Consigli?
Grazie.
Lupin
-------------------------
http://www.favoriti.it/
Importa e gestisci i tuoi bookmarks on-line
----------------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------
Rimuovere XXX per rispondere via e-mail

La mia voglia di passare a MySQL aumenta di giorno in giorno.... ;)
--
:: Fate i bravi e non clonate le pecore!
:: Distractly yours... 
man...@ufologia.net

 accettabili.
[CUT]
Utilizzi degli indici? (spesso [se usati correttamente] si notato
"pesantemente"....)
Gusher-

> La mia voglia di passare a MySQL aumenta di giorno in giorno.... ;)
[CUT]
Bhč.. MySQL č un "giocattolino" (rispetto a SQLServer) ed anche piuttosto
limitato.
Gusher.

Su che basi dici questo? Se ne era già parlato qualche tempo fa e avevo
riportato diversi test comparati, alcuni anche complessi dove risultava che
quel giocattolino potesse competere con Oracle 9i


 quel giocattolino potesse competere con Oracle 9i
Intermini di velocità è mooooolto veloce MySQL, sopratutto quando parli di
BulkInsert, Update...
Riguardo Integrità, SubQueries, StoredProcedure, Triggers etc..: scordatele.
Cmq. basta che apri il Sql Reference di MySQL e confrontarlo con SQLServer..
per capire
che effettivamente SQL Server è un  RDBMS a tutti gli effetti(a differenza
di MySQL).
Gusher.

 quel giocattolino potesse competere con Oracle 9i
http://www.tpc.org/tpcc/results/tpcc_perf_results.asp?resulttype=all
potranno anche essere risultati "campanilisti", ma queste sono le aziende
che li ritengono validi:
http://www.tpc.org/information/who/whoweare.asp
C'è IBM, c'è MS, c'è anche Oracle, c'è Sun... e solo per aver messo
d'accordo qsti signori vuol dire che un valore quei numeri lo hanno. Ma
tutto, ovviamente, è opinabile...
..A
UGIdotNET - 
http://www.ugidotnet.org


beh, puoi usare (come tu stesso dici) la clausola TOP, "prelevando" solo i
dati della pagina che ti serve.


 Gusher.


"pesantemente"....)
Certo, i campi sono indicizzati.
Lupin
-------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------
http://www.favoriti.it/
Importi i tuoi bookmarks e li gestisci on-line
----------------------------------


 punto di vista.
Penso che chiunque usa SQLServer, non invidia MySQL =)
Gusher.

 tutto, ovviamente, è opinabile...
Io sono del parere che un database va scelto in base a quello che si vuol/si
deve fare.
Sicuramente IBM, MS & company hanno adottato MySQL perchè effettivamente non
avevano grosse "esigenze" (a livello di funzionalità) per
quello che dovevano fare.
Gusher.


eheheheh... hai proprio ragione. Il prob di SQL Server, a mio avviso, è il
tipico "problema" delle tecnologie MS: molto immediato nell'utilizzo, ti fa
sentire subito produttivo e non ti spinge ad approfondire. E spesso le
ragioni della propria insoddisfazione nascono a causa di questa
"dinamica"...


Internally, through a new .frm file format for table definitions, MySQL 4.0
lays the foundation for the new features of MySQL 4.1, such as nested
subqueries, stored procedures, and foreign key integrity rules, which form
the top of the wish list for many of our customers. Along with those, we
will also include simpler additions, such as multi-table UPDATE statements
Ed è esattamente quello che sto aspettando, altrimenti sarei già passato a
MySQL senza pensarci un attimo! :)
Accidenti dovrò fare a meno dei trigger... ;)


Riguardo Integrità, SubQueries, StoredProcedure, Triggers etc..: scordatele.
Hai ragione, MySQL non supporta StoredProcedure e Triggers, ma ti
assicuro che la velocita' in ambito di applicazioni Web e siti Web
dinamici e' molto piu' importante. Tra l'altro quasi tutto quello che
fai con StoredProcedure e Triggers lo puoi fare spostando tutto a
livello di applicativo (ASP, PHP......), e lo stesso vale per
l'integrita', anche se il fatto che venga gia' supportata dal DBMS e'
sicuramente un vantaggio.
Lupin
-------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------
http://www.favoriti.it/
Importi i tuoi bookmarks e li gestisci on-line
----------------------------------


dati della pagina che ti serve.
Scusa ma la query devo eseguirla cmq, poi gli do' i parametri di
paginazione, per cui cosa cambia?
Correggimi se sbaglio.
Lupin
-------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------
http://www.favoriti.it/
Importi i tuoi bookmarks e li gestisci on-line
----------------------------------


 Lupin


 Lupin




Ok, ma in questo modo come seleziono i record della pagina 3, che
vanno dal record 21 al record 30?
Lupin
-------------------------
http://www.favoriti.it/
Importa e gestisci i tuoi bookmarks on-line
----------------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------


cursori, seppur comodi, vanno evitati... e tante altre cose.
Ok, ho anticipato che non sono espertissimo di ASP e SQL server, puoi
darmi qualche consiglio per migliorare le prestazioni?
Es., questo e' il codice che utilizzo per connettermi, e' corretto?
Esiste qualcosa di piu' performante?
Set conn = Server.CreateObject("ADODB.Connection")
conn.ConnectionTimeout = 15
conn.Open "Provider=sqloledb;Network Library=DBMSSOCN;Data Source=" &
mssql_host & ",1433;Initial Catalog=" & mssql_db_name & ";User ID=" &
mssql_username & ";Password=" & mssql_password & ";Encrypt=yes"
Ripeto, io ho gia' problemi di prestazioni su una tabella di 20000
record, la query, anche eseguita da query analyzer (quindi qua ASP non
c'entra) impiega 600ms (profiler) per essere eseguita, tempo che mi
sembra eccessivo. A me in realta' servono solo i record es. dal 51 al
60, ma come faccio a dirglielo?
Lupin
-------------------------
http://www.favoriti.it/
Importa e gestisci i tuoi bookmarks on-line
----------------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------


 60, ma come faccio a dirglielo?
Progettando il DB con una bella chiave ID con il numero di record (e ci sono
i campi Identity apposta) e mettendo la condizione di where nella query? Non
lo hai fatto così? Allora sono un po cazzi tuoi, devi aprire per forza un
cursore server side (invece che client side), fare una move al record che ti
serve e leggere i dati, però è una soluzione meno scalabile e più scomoda
rispetto ad un recordset completamente client side. Per inciso questo
sistema è quello che usa mySQL, la differenza è che con SQL Server ed Ado tu
puoi *scegliere* se usare un cursore lato server o lato client e se poter
usare o no il recordset in modo disconnesso, in modo da avere performance
più o meno scalabili a seconda delle necessità e di come viene fatto il DB.
Saluti
Massimo

 50esimo al 100esimo.
Sei hai a disposizione sql server, usa le stored procedure. Non sentirai la 
mancanza dei Limit di mysql e postgresql...
Ciao
--
AZ 

più o meno scalabili a seconda delle necessità e di come viene fatto il DB.
E con la differenza che con MySQL posso stabilire *direttamente nella
query* quali record voglio, quindi non mi interessa nulla di avere il
recordset lato client.



faccio un esempio banale, ma spero significativo: SQL Server è un RDBMS,
quindi avrai predisposto una chiave primaria nella tua tabella (prob è anche
un indice clustered). A qsto punto, alla prima pagina fai una SELECT TOP 20
che ti recupera le prime 20 righe e ti memorizzi il valore dell'ultima
chiave primaria mostrata. Alla richiesta della pagine seguente, fai un'altra
estrazione, che recupera i primi 20 record la cui PK sia superiore
all'ultima mostrata nella pag precedente. Ripeto: l'esempio vuole solo
mostrare un approccio, e non essere esaustivo.


 recordset lato client.
Allora non hai capito. Siccome mySQL non è magico quando tu dici
"*direttamente nella query*" gli stai dicendo di aprire un cursore lato
server, scorrere il resultset e mandarti indietro i record che ti servono.
Fidati di me, questa operazione sarà anche comoda ma *non è* performante e
scalabile.
Questa modo di operare su mySQL risulta nel fatto che, alla fine, devi
lavorare *solo ed esclusivamente* così e dipende da come è fatto dentro, ed
è il motivo che, per quanto sia un bell'oggetto, non ha le garanzie di
performance e scalabilità che hai con SQL Server (o con Oracle o con un
altro database relazionale serio).
Il fatto che su mySQL fare una cosa come la paginazione risulti semplice non
vuole dire che sia meglio, anzi!
Saluti
Massimo

 lo hai fatto così? Allora sono un po cazzi tuoi
Scusa ma che c'entrano gli ID identificativi dei record?? Se io faccio un
ordinamento per un qualunque campo diverso dal campo Identity l'ordine degli
ID è indifferente...
Diciamo che io ho TABELLA_A (oltretutto semplificando solo ad un campo di
ricerca)
CAMPO_ID identity
NOME varchar(50)
CAMPO_ID = 1
NOME = 'Ziocantante'
CAMPO_ID = 3
NOME = 'Armando'
CAMPO_ID = 4
NOME = 'Giusi'
Voglio una paginazione che mi visualizzi un risultato per pagina e
chiaramnete voglio i risultati ordinati per cognome.
SELECT CAMPO_1,NOME FROM TABELLA_A ORDER BY NOME
La sequenza degli ID risultanti sarà 3, 4, 1
Non vedo la correlazione che potrestisfruttare per ottenere un ordinamento a
pagine. Illuminami...


Andrea ma che c'entra l'ordinamento della chiave primaria con il resto?????
Questo ha un senso se tu fai l'ordinamento per chiave primaria (cosa che
accadrà in un caso su 20) altrimenti il discorso cade... (vedi esempio che
ho postato sopra)


 ho postato sopra)
Le usa per "simulare" quel maledetto statment LIMIT di MySQL.
Gusher.

Ma non puņ funzionare Gusher! :) Leggi l'esempio banale che ho riportato
sopra



Ovviamente l'approcio che ho suggerito io non funziona se sulla query da
paginare devi supportare ordinamenti differenti. In questo caso l'unica
possibilità è quella del cursore server side, con tutti i problemi di casi.
Saluti
Massimo

scalabile.
Ho capito ma la stessa cosa non riesci a repricarla con SQL server,
devo ricorrere alla paginazione di ADO, che e' ad uno strato sotto, e'
piu' lenta!!
Forse non mi sono spiegato ma si tratta di un'applicazione Web, a cosa
mi serve il cursore lato client in un'applicazione Web, il client non
e' sempre il server Web? Non ho sempre convenienza che i cursori siano
lato server?
Lupin
-------------------------
DaDaBIK - DaDaBIK is a DataBase Interfaces Kreator
http://www.dadabik.org/
-------------------------
http://www.favoriti.it/
Importi i tuoi bookmarks e li gestisci on-line
----------------------------------


 lato server?
No, perchè un cursore TI CONSUMA DELLE RISORSE SUL DB. Se invece usi un
cursore lato client la connessione dura il più breve tempo possibile (quello
di portare i dati dal DB server al Web Server) e poi tutto viene fatto sul
web server, la connessione viene liberata ed il DB è di nuovo libero di
servire altri client. Se le operazioni che fai sul recordset una volta
aperto solo banali probabilmente non troverai tanta differenza (ma comunque
c'è, fidati che c'è), se invece devi fare dei conti un attimo più complicati
vedrai che una differenza la trovi, eccome.
Saluti
Massimo

Guarda Lupin, tempo fa ho fatto diverse ricerche per capire quale fosse il
metodo più efficnete (in termini di prestazioni e scalabilità) per fare la
paginazione. Ho letto diversi metodi, paginazione in tabelle temporane
attraverso SP, paginazione lato client, ecc ecc.
Alla fine il metodo "migliore" risultava essere questo:
Aprire tutto il recordset con cursore FORWARD ONLY (tutto lato client).
(Se i record sono tantissimi e non li visualizzi tutti in una pagina puoi
anche mettere un TOP qualcosa...)
Spostare il recordset al punto desiderato (rsTemp.Move)
Trasferire il recordsat in una matrice (arrTemp = rsTemp.GetRows)
Chiudere il recordsat e operare con l'array.
