Newsgroup: it.comp.lang.visual-basic
Titolo: Velocizzare l'accesso a file DBF

Ciao,
ho la necessità di interrogare (in sola lettura) un database DBF da 200
MB (uno stradario).
Ora, con ADO una query impiega circa 30 secondi per essere eseguita...
Esiste un modo più veloce per farlo?
Tnx.
Daniele.

 Esiste un modo piů veloce per farlo?
Senza conoscere la query č bella dura.
Prima di tutto verifica che i campi su cui fai la ricerca siano indicizzati. 
La fonte primaria di lentezza di esecuzione di una query e' l'assenza dei 
corretti indici, ove necessari. Poi verifica che la query stessa sia 
ottimizzata. Per esempio se vuoi verificare che l'anno in un campo data sia 
(es.) maggiore di un valore, piuttosto che:
... WHERE YEAR(campo_data)>1990
la quale obbliga il motore a fare una scansione completa della tabella, 
valutando record per record YEAR(campo_data), puoi usare:
... WHERE campo_data>'1990-01-01'
che sfrutta gli indici di colonna.
Una buona lettura, che anche se riferita a MySQL, č valida anche per gli 
altri DB, č:
http://www.databasejournal.com/features/mysql/article.php/10897_1382791_1
Ovviamente, se possibile, trarresti gran beneficio esportando il DB per 
accedervi con un DB Engine piu' moderno =)
hth,
Lokar 

Barzo ha usato la sua tastiera per scrivere :

Sicuramente.
30" sono un tempo infinito per una query.
A meno che non si sia in rete, che nel caso dei db file-based è un 
disastro.
Anche con un DX266 e 16MB di Ram, una query normale deve impiegare 
meno.
Posta la query e vediamo un po'.
Alberto
-- 
Heinrich Zille: Ognuno crede che l'altro sia come se stesso, 
dimenticando che al mondo esistono anche delle persone oneste.

 ... WHERE campo_data>'1990-01-01'
Chiedo scusa per l'imprecisione, ovviamente la condizione equivalente e':
WHERE campo_data>'1990-12-31'
Lokar

 accedervi con un DB Engine piu' moderno =)
Infatti ci avevo pensato...
Io uso Firebird come DB Server, ma volevo evitare di fare importazioni
per mettermi al riparo dai vari aggiornamenti del DB in questione...
Cmq...la query è abbastanza semplice:
SELECT * FROM Street.dbf
WHERE IND_CITY = 1530 AND FULLNAME LIKE '%VERDI%'
Questa query ritorna 3 record!
All'inizio pensavo che fosse il LIKE il responsabile...ma eseguendo la
query senza, il risultato non cambia.
Tnx!
Daniele.

 Posta la query e vediamo un po'.
L'ho postata rispondendo a Lokar!
Tnx.
Daniele.

 query senza, il risultato non cambia.
Dando per scontato che il file sia in locale (perchè nell'altro 
messaggio indicavo che se siamo in rete cambia il ragionamento, ma tu 
non hai detto niente al riguardo), una query come quella può impiegare, 
anche su tabelle da alcune centinaia di migliaia di record, da qualche 
centesimo per i dbms server a qualche secondo per i dbms file-based. Ma 
sicuramente non 30".
Voto per aggiungere e forzare l'utilizzo degli indici.
Per sapere *come* aggiungere e forzare l'utilizzo degli indici, occorre 
sapere di che db si tratta, perchè l'estensione dbf è utilizzata da 
diversi dbms, come DB3, DB4, FoxPro, e altri...
Ciao
Alberto
-- 
Charles Baudelaire: C'è un solo modo di dimenticare il tempo: 
impiegarlo.

 query senza, il risultato non cambia.
Prima di tutto, non usare * ma esplicita i campi che vuoi ritornare
(anche fossero tutti).
Verifica che IND_CITY sia di tipo numerico, e se non lo e' confrontalo
con un dato di tipo adatto (non usare le conversioni implicite).
LIKE rallenta, ma la query in nessun caso puo' durare 30 secondi, neanche
con centinaia di migliaia di record.
In presenza di un indice su FULLNAME, puoi ottimizzare ulteriormente il
confronto fra stringhe eliminando il primo % e usando quindi LIKE 'VERDI%',
sempre che questo soddisfi ancora la ricerca che vuoi fare. Ancora meglio
se la ricerca la fai sempre sui primi N caratteri (ad esempio i primi 10)
puoi creare un indice parziale anziche' su tutta la colonna.
Alberto sapra' senz'altro darti indicazioni migliori, ma io punto i miei
2 eurocent sugli indici.
hth,
Lokar

 ... neanche con centinaia di migliaia di record.
Se non l'avessi scritto io direi di aver copiato...
Del resto ho avuto un bravo maestro... di cui pero'
sono diventato solo la brutta copia :|
Lokar ;)

 diversi dbms, come DB3, DB4, FoxPro, e altri...
Infatti!
La cosa che non mi spiego è perchè, nell'applicazione del fornitore del
DB, le ricerche sono pressochè immediate!
Ora, chiaramente non conosco l'implementazione e gli strumenti
utilizzati, l'unica cosa che posso constatare è che le loro ricerche
sono veloci anche se non hanno indici!! :-(
Daniele.

 sono veloci anche se non hanno indici!! :-(
200MB di DB non sono molti. Forse buttano tutto il DB in memoria, magari 
indicizzandolo li' (con l'uso di hashtable o affini).
Tienici aggiornati con le evoluzioni :)
Lokar 

Lokar ha scritto:

Si, non sono moltissimi (sono poco + di un milione di records)...
Anche io ho provato a caricare tutto in all'apertura ma aprendolo così:
 Open "SELECT IND_CITY, FULLNAME FROM Street.dbf",
      DbfConn,
      adOpenDynamic,
      adLockOptimistic,
      adCmdText
L'apertura ovviamente è istantanea ma l'applicazione dei filtri è
lentissima!!
Adesso provo a chiedergli come fanno....ormai sono curioso!
Ciao!
Daniele.


Dunque...dopo un po' di tempo sono nuovamente sul problema.
Ho aggiunto gli indici CDX utilizzando FoxPro.
(Tra l'altro non so perchè il fornitore mi aveva detto che erano in
formato DB3 ma DBASE non riconosce valido il formato!!)
Ora ho creato gli indici sui campi FULLNAME e IND_CITY ma, quando
esegui la query:
SELECT * FROM Street.dbf
WHERE IND_CITY = 1530 AND FULLNAME LIKE '%VERDI%'
Mi ritorna l'errore: Indice non trovato
(la query all'interno di FoxPro funziona ed è velocissima!)
mentre se faccio:
SELECT * FROM Street.dbf
WHERE FULLNAME LIKE '%VERDI%'
funziona..ma è lentissimo lo stesso!
Ora, io sto usando il driver ODBC per DBase (ho provato con quello per
FoxPro ma non funge!)
Avete qualche suggerimento?!?
Tnx.
Daniele.

 FoxPro ma non funge!)
Forse non stai usando il provider giusto (DBase aveva diverse versioni, 
anche dbIII esiste in diverse sottoversioni).
Oppure gli indici che hai creato sono in un formato diverso da quello 
che si aspetta il provider (il che ha un senso, se hai creato gli 
indici con foxPro e cerchi di usarli con dbIII).
Cercherei di scoprire, googlando un po', se esiste modo di identificare 
esattamente il formato del db (ad esempio con un editor hex o similia).
Ciao
Alberto
-- 
Konrad Adenauer: All'intelligenza Dio ha posto limiti, alla stupidità 
no.

 > DBF gli indici sono file NTX)..
Dunque...dopo un po' di tempo sono nuovamente sul problema.
Ho aggiunto gli indici CDX utilizzando FoxPro.
(Tra l'altro non so perchè il fornitore mi aveva detto che erano in
formato DB3 ma DBASE non riconosce valido il formato!!)
Ora ho creato gli indici sui campi FULLNAME e IND_CITY ma, quando
esegui la query:
SELECT * FROM Street.dbf
WHERE IND_CITY = 1530 AND FULLNAME LIKE '%VERDI%'
Mi ritorna l'errore: Indice non trovato
(la query all'interno di FoxPro funziona ed è velocissima!)
mentre se faccio:
SELECT * FROM Street.dbf
WHERE FULLNAME LIKE '%VERDI%'
funziona..ma è lentissimo lo stesso!
Ora, io sto usando il driver ODBC per DBase (ho provato con quello per
FoxPro ma non funge!)
Avete qualche suggerimento?!?
Tnx.
Daniele.
mi sembra di ricordare che gli indici per i dbf:
- nativi dBase, sono ndx (db3), mdx (db4). almeno i primi vb direi li 
vedesse.
- ntx sono di clipper. dbase non sa proprio cosa siano. vb anche meno, salvo 
librerie tipo apollo
- cdx sono di foxpro, clipper5 direi li possa vedere, dbase no.
a occhio, nelle tue query:
nella prima, non vede l'indice, quindi l'=1530 non riesce a usarlo.
nella seconda, fa una ricerca sull'intero campo, quindi l'indice non gli 
serve a niente e manco a prova a cercarlo.
sempre se ricordo, puoi provare a fargli creare gli ndx con db3 e vedere se 
vb li riconosce. nel caso, dovresti guadagnare qualcosa.
hth, ciao, a.

 anche dbIII esiste in diverse sottoversioni).
non mi sembra. una ne e' uscita e una continuo a tenere zippata. piu' o meno 
lo stesso per db4, se ricordo. e' che i vari dialetti (compilati, quindi 
parecchio piu' veloci ed efficienti) hanno incasinato le cose dal pdv dello 
standard dbase/dbf. clipper p.e. poteva avere campi testo di 1000 byte 
indicizzabili, cioe' non memo. e ognuno si e' creato la struttura di indici 
che preferiva.
ciao, a.

 formato DB3 ma DBASE non riconosce valido il formato!!)
Quando si allega o si apre una tabella dBASE, è possibile indicare al
modulo di gestione di database Jet di utilizzare uno o più file di 
indice dBASE (NDX o MDX) per migliorare le prestazioni. Il modulo di 
gestione di database Jet registra gli indici in un particolare file 
di informazioni (INF). Quando si utilizza Visual Basic per allegare o
aprire una tabella dBASE, è necessario creare il file INF utilizzando
un editor di testo oppure utilizzare il file creato in Microsoft 
Access. È necessario che il nome del file INF corrisponda al nome 
della tabella esterna. Per fare in modo che il modulo di gestione di 
database Jet individui facilmente gli indici associati, è 
consigliabile collocare il file INF nella stessa directory della 
tabella associata. Tuttavia, se la tabella si trova in una risorsa 
condivisa di sola lettura, è possibile specificare un percorso 
diverso utilizzando la voce INFPath nelle impostazioni di 
inizializzazione.
Ciascuna voce del file INF contiene un numero di indice (che utilizza
gli identificatori NDXn per dBASE III, NDXn o MDXn per dBASE IV) e un
nome file di indice (ad esempio, COGNOME.NDX). Le voci sono precedute
da un tipo di database di origine. Ad esempio, il file INF per una 
tabella dBASE III denominata Autori potrebbe essere AUTORI.INF e 
potrebbe contenere le seguenti voci.
[dBASE III]
NDX1=IDAutore.NDX
NDX2=Cognome.NDX
NDX3=Cap.NDX
Per specificare un indice univoco, aggiungere il descrittore o il 
nome del file per l'indice univoco al file INF utilizzando 
l'identificatore UIDXn. Aggiungere la voce sotto l'intestazione del 
tipo di database, come mostrato nel seguente esempio.
[dBASE III]
NDX1=IDAutore.NDX
NDX2=Cognome.NDX
NDX3=Cap.NDX
UIDX1=IDAutore.NDX
Quando si utilizza il modulo di gestione di database Jet per 
aggiornare i dati del file DBF, Jet aggiorna anche i file di indice 
per riflettere le modifiche apportate. Se si allega o si apre un file
DBF e si associa un file di indice (NDX o MDX), è necessario che il 
modulo di gestione di database Jet sia in grado di trovare il file di
indice per aprire la tabella allegata. Se i file di indice o il file 
INF vengono eliminati o spostati, il modulo di gestione di database 
Jet non è in grado di utilizzare l'indice e quindi di aggiornarlo. Se
i file di indice non sono correnti, i risultati della ricerca non 
saranno prevedibili.
-- 
All computers run at the same speed...with the power off.
News 2002 [v 2.07] / StopDialer / PopDuster - 
http://www.socket2000.com
Akapulce portal: 
http://www.akapulce.net