Newsgroup: it.comp.lang.visual-basic
Titolo: Sottoquery lentissima

DB access
Vorrei estrarre Codice, Cognome da Tab1 a condizione che Codice si presente 
in Tab2, quindi ho fatto cos�:
Select Codice, Cognome from Tab1 where Codice In (select Codice from Tab2)
Ma il risultato � lentissimo! Tab1 ha 20.000 righe e tab2 solo 2.000; il 
campo Codice delle 2 tabelle � un cmapo testo di 5 caratteri.
Lentissimo intendo che dopo 2-3 minuti tra trovato solo 4-500 record.
Eseguendo la query direttamente in access si vede la tabella che si popola 
poco alla volta e se forso lo scrolling mando in blocco access.
Secondo voi dove � sbagliata la query?
Grazie per goni info
Greg

 Secondo voi dove è sbagliata la query?
Anche se stiamo parlando di Access, non dovrebbe essere così lento su
una operazione del genere con quei numeri... prima domanda, terra-
terra: chiavi primarie e indici sono a posto, in particolare per il
campo Codice di entrambe le tabelle??

 Select Codice, Cognome from Tab1 where Codice In (select Codice from Tab2)
Come sono gli indici (o chiavi primarie) ?

Partendo dal presupposto che la tabella Codice sia una "anagrafica", ossia
che abbia il campo "codice" come chiave primaria, o comunque mai ripetuto,
se vuoi toglierti la curiosit�, una volta sistemati gli indici/chiavi, puoi
provare anche queste due alternative, equivalenti alla tua, per vedere se ci
sono differenze nelle performances:
SELECT T1.Codice, T1.Cognome
  FROM Tab1 T1
      ,Codice T2
 WHERE T1.Codice = T2.Codice
oppure
SELECT Codice, Cognome
  FROM Tab1 T1
 WHERE EXISTS (SELECT 1
                 FROM Codice T2
                WHERE T1.Codice = T2.Codice
              )

 Secondo voi dove ï¿œ sbagliata la query?
Beh, non sappiamo come sia strutturato il db.
In linea di principio, io quando devo cercare 'i mancanti' uso il Left 
Outer anzichï¿œ una nested query. Un motore dignitoso, con un mezzo 
indice che sia definibile tale, ti trova i risultati in pochi decimi di 
secondo.
SELECT DISTINCT A.CODICE, A.COGNOME
FROM TAB1 AS A
LEFT OUTER JOIN TAB2 AS B
ON A.CODICE = B.CODICE
WHERE B.CODICE IS NULL
(scrivo a braccio e con sintassi TSql, adattala ad Access).
Ho aggiunto il Distinct perchï¿œ non so se 'codice' sia Unique su 
entrambe, e vorrei evitare la moltiplicazione stile 'prodotto 
cartesiano' dei dati. Ovvio che se Codice ï¿œ Unique, togliendo Distinct 
le performance migliorano.
Se poi Codice ï¿œ Clustered su entrambe le tabelle (ammettendo che Access 
gestisca l'indicizzazione Clustered), la query ï¿œ istantanea.
Ovvio che se hai 20.000 record da una parte e 2.000 dall'altra, a meno 
di doppioni dovresti avere circa 18.000 record di ritorno.
Il che comporta un notevole tempo di trasferimento dati in rete e 
soprattutto di popolamento del controllo client di visualizzazione (ad 
esempio il datagrid). Ma questo lo sai solo tu (come sia la rete e 
quale sia il controllo di destinazione).
Se parliamo della sola query, con un Left Outer Join anzichï¿œ una nested 
query dovresti avere decisi miglioramenti.
Alberto
-- 
Heinrich Zille: Ognuno crede che l'altro sia come se stesso, 
dimenticando che al mondo esistono anche delle persone oneste.

 In linea di principio, io quando devo cercare 'i mancanti'
Scusa, vedo solo ora che cercavi i presenti, non i mancanti.
Ma allora ï¿œ un normalissimo Inner Join con al piï¿œ un distinct (se 
Codice non ï¿œ Unique sulla seconda tabella), perchï¿œ mai incasinarsi con 
una nested query?
Alberto
-- 
Fabio Fazio: Se siamo alleati come mai nei nostri bar si vende Coca 
Cola e nei bar americani non si vende l'amaretto di Saronno?

 Outer anzich� una nested query.
...
Mi sa che a lui serve il contrario, cioe' quello che avrebbe utlizzando una 
Inner Join

 query?
...
Vabbe', ignora la mia risposta di 2 minuti fa :-)

 ha scritto nel messaggio 
news:4ac5f86a$1...@news.x-privat.org...

Nella prima tabella � chiave primaria, nella seconda invece no
greg

 Nella prima tabella ï¿œ chiave primaria, nella seconda invece no
Il fatto che non sia chiave primaria non significa che non possa essere 
unique e clustered (cosa che darebbe benefici immani).
Alberto
-- 
Charles Baudelaire: C'ï¿œ un solo modo di dimenticare il tempo: 
impiegarlo.

 Alberto
Scusa Alberto, hai ragione, ma il motivo � che la query risultante deve 
essere editabile, e con la inner non riesco a scrivere.
Sulla seconda tabella il codice non � unique, duplicati ammessi, consentiti 
e presenti.
greg

 Nella prima tabella � chiave primaria, nella seconda invece no
Ok.
Crea un indice anche sulla seconda.

 unique e clustered (cosa che darebbe benefici immani).
Stiamo parlando di access, quindi non ha molta scelta.

 e presenti.
Si, ma c'� un indice per codice, o almeno un indice che contenga il codice
come primo campo ?

 come primo campo ?
Nessun indice e non posso farci nulla perch� � una tabella collegata su un 
sqlexpress
greg 

 sqlexpress
Non conosco.. quindi l'indice non � sfruttabile ?
Hai provato con la join diretta ?


 WHERE T1.Codice = T2.Codice
Si, velocissima, anche non proprio come la scrivi tu, ma non ci posso 
scrivere dentro
greg 

 scrivere dentro
In che senso scrivere dentro ?

ToSka ha scritto:

Nel senso che devo editare i campi della query risultante, come fosse una 
tabella
-- 
Greg 

 tabella
...
Diciamo che devi modificare il *risultato* della query :-)

 wrote in news:ha56uf$av6$
1...@tdi.cu.mi.it
:

se avessi messo nel primo post almeno qualcuno dei dettagli che ti hanno 
estratto a forza finora, magari si faticava meno a capire la tua 
situazione e quello che vuoi ottenere...
una possibilita' potrebbe essere usare una tabella d'appoggio locale in 
cui copi solo il campo 'codice', usando distinct e quant'altro per non 
avere duplicati, e poi il join lo fai con la tabella locale.
le prestazioni dovrebbero migliorare un po'.
non so pero' se sia una soluzione utilizzabile nel tuo caso.
quanto spesso cambiano i dati remoti?
quanto spesso li devi elaborare?
con che velocita' ti serve ottenere il risultato dell'elaborazione?
il file access e' veramente 'locale' o accedi via rete?
se buona la seconda, in quanti lo usano?
al solito, quello che non ci dici, non lo possiamo considerare nel 
proporti alternative...
-- 
Paolo opg
BE AWARE that this post uses a fake reply-to address
to contact me write to:
janickg ( at ) hotmail ( dot ) com
--

 Greg
Non funziona così....per access è quello che per altri db è una vista
(view)...una istantanea dei tuoi dati selezionati!
per cambiare i dati vai a manina...tabella per tabella (anche perchè
una tabella non hai detto ora è su SQL server???...ti immagini i
casini potenziali se ti fa mischiare pere e bulloni???)
Cmq una Select
SELECT TAB1.Nome, TAB1.Cognome,
FROM TAB1 INNER JOIN TAB2 ON TAB1.Codice = TAB2.IDCodiceSQLexpress;
prova ad aprire access e (cambiando i nome dei campi) incollala in una
nuova query
A me rende modificabile la tabella (ci mancherebbe altro)
Il problema semmai è l'sqlExpr....che è in rete...che ti deve
autenticare....processare la richiesta e rispondere.
Se poi l'hai sul solito pc (...casomai hai aperto l'ambiente di
sviluppo...e access... e sql server che per risponderti è attivo ...e
per puro caso stai anche ascoltando una web radio...e per finire il
mulo o il torrente attivo!???!!)...è lui che poveretto come servizio
lo stai stressando!!!
e per finire colleghi sqlserv con odbc?
BLAM....esplode il pc eh eh eh!
La riprova di quello che dico?
Prendi tabella2 e esportala su un altro mdb...ferma l'agente o il
servizio di sqlexpress. Chiudi tutte le app inutili!
prova a collegare al posto di sqlserver ...l'altro mdb di
access...voilà!
se va piano come prima....cambia pc...è l'ora di  pensionare il p3!

 non avere duplicati, e poi il join lo fai con la tabella locale.
Si, alla fine ho risolto cosi
-- 
Greg 

 se va piano come prima....cambia pc...� l'ora di  pensionare il p3!
Si alla fine ho fatto cosi, ma sempre con sttoquery.
La velocit� adesso � ottima.
Lunedi provo anche inner
-- 
Greg