Newsgroup: it.comp.lang.delphi
Titolo: [BDE] Rallentamenti anomali in concorrenza tquery

Ho gia' scandagliato google groups,il sito borland e 
www.bdesupport.com
 a
fondo,senza ottenere risposte soddisfacenti: il problema e' il classico
degrado delle prestazioni accedendo agli stessi archivi da due diverse
postazioni.
BDE: alias puntato ad una directory sul server (win2k3) contenente file DBF
con indici MDX.
Applicativo: ho messo nell'unico datamodule utilizzato un TDatabase che punta
all'alias BDE, tutti gli oggetti ttable e tquery delle form puntano ad esso.
L'alias BDE l'ho creato con un programmino che sfrutta l'oggetto TSession,
seguendo alla lettera la guida di delphi.
Andando a vedere col BDE administrator i parametri dell'alias che ho creato e
che utilizzo per il mio programma, ho solo questi tre:
DEFAULT DRIVER = DBASE
ENABLE BCD = FALSE
PATH K:\DB\AZIENDA\
L'applicativo viene compilato sul disco di rete, e i client invocano lo stesso
eseguibile (ho provato anche a farne una copia per ognuno, sia su disco di
rete che in locale, ma il rallentamento permane).
Qualcuno di voi ha avuto questi problemi? e come li ha risolti? 
Nello specifico,la configurazione dell'alias bde e' soddisfacente oppure
bisogna aggiungere altri parametri?
Ciao e grazie,
-- 
Morde. 
(
mo...@despammed.com
)
M-List di icld: 
http://it.groups.yahoo.com/group/icld/

 bisogna aggiungere altri parametri?
Non hai indicato se lo fai, ma la TSession.PrivateDir dovrebbe essere
impostata ad un percorso locale. Se non lo fai e l'applicazione viene
eseguita da un server, rischi che tutti i file temporanei (e quindi i
risultati delle query) vengano creati sul server, oltre ad eventuali
conflitti creati dalle varie istanze dell'applicazione.
I dettagli nella guida di Delphi.
Oltre a questo, puoi provare a rivedere un pò la struttura della query, in
relazione al problema che ti si pone.
In particolare:
1. puoi introdurre un'eventuale ottimizzazione creando un indice che
rispetti la clausola ORDER BY della query;
2. non vorrei dire castronerie, ma trattandosi di BDE la query dovrebbe
essere elaborata localmente (significa che le tabelle utilizzate vengono
lette per intero prima di applicare le condizioni di filtro ed ordinamento),
quindi potresti preferire all'uso dell'oggetto TQuery un TTable al quale
avrai impostato opportunamente indice (per l'ordinamento dei dati) e le
proprietà Filtered e Filter o l'evento OnFilterRecord. In questo modo
distribuisci la selezione e l'elaborazione dei dati man mano che
effettivamente servono senza dover creare l'immagine locale di tutti i dati.
Questo ti viene molto utile se i dati vengono visualizzati nell'interfaccia
utente (praticamente hai un minimo ritardo nell'apertura del form).
Ciao,
Gianluca.
-- 
Gianluca Plevani
-----------------------------------------------------------
http://www.brain-enterprise.com

del tipo che se lavora un solo pc va come un treno e hai un sensibile 
decadimento di performance quando parte il secondo?
AS

 proprietà Filtered e Filter o l'evento OnFilterRecord. 
In effetti hai fatto un po' di confusione: accade esattamente il contrario.
Se esegui una query, sul filo che collega il tuo pc al server dei dati
viaggiano i soli dati rispondenti ai criteri di selezione impostati nel
testo SQL, mentre se effettui un filtering lato client (con una ttable)
sulla rete viaggiano tutti i record, che poi vengono opportunamente
filtrati dall'applicazione.
Cito l'help: "TTable provides direct access to every record and field in an
underlying database table", mentre a proposito delle TQuery "Automatically
access a subset of rows and columns in its underlying table(s), rather than
always returning all rows and columns".
Magari per provare puoi fare così: ti crei una tabella con 5.000.000 righe,
poi provi a selezionarne una sola con una query sul campo indice oppure con
una ttable filtrata: vedrai le performance passare da un istante (tquery) a
parecchi secondi (ttable).
Saluti
	Marco Bortolani
	info @ 
marcobortolani.it

 stessi archivi da due diverse postazioni.
Hai controllato che la net dir non sia nella stessa cartella dell'eseguibile
?
Dicono possa dare problemi.
Ho un documento in inglese (un pò vecchiotto) che spiega vari settaggi e
configurazioni.
Se ti serve fammi un fischio ....
Giulio

proprietą Filtered e Filter o l'evento OnFilterRecord. 
Giusta intuizione, applicata gia' anche da me in determinati punti (ad esempio
per filtrare tutte le righe di un ordine) risultato: sempre il medesimo tempo
biblico.
Stiamo anche verificando le prestazioni della lan, non vorrei ci fosse qualche
problema.


decadimento di performance quando parte il secondo?
Anche in monoutenza le performance decadono in maniera insolita.


Se ti serve fammi un fischio ....
Grazie, verifico il suggerimento, manda pure il documento su
mo...@despammed.com
 :-)
Ciao


Andrea LF segnalava che le tquery di bde ignorano gli indici su paradox.
Non è che accade lo stesso anche per i dbf?
AS

"Marco Bortolani" ha scritto nel messaggio
[CUT]
Probabilmente mi sbaglio, ma quello che dici mi sembra sia valido se
dall'altra parte c'è un database server che accetta la richiesta SQL e di
seguito la elabora.
Nel caso del BDE con tabelle DBase o Paradox, non esiste un server che
riceve richieste e quindi tutta l'elaborazione è a carico del PC client
(oppure sto impazzendo? io uso tranquillamente applicazioni in rete dove sul
server ci sono solo i file fisici Paradox con il BDE installato solo client)
indipendentemente dal tipo di oggetto (TQuery o TTable) che stai
utilizzando. Con altri database server è un'altro discorso.
Quindi, se questo è vero, in termini di prestazioni non cambia niente, con
la differenza che utilizzando TQuery, tutta l'elaborazione di selezione ed
ordinamento viene nel momento in cui la query viene aperta, mentre
utilizzando TTable, indice e Filter (oppure OnFilterRecord) il carico di
lavoro viene "distribuito" man mano che i record vengono prelevati dal
server (utile se i dati vengono rappresentati in una Interfaccia Utente).


 col lifecycle del programma.
Quindi la dir corrente è una cartella locale, non quella da cui esegui
l'applicazione (che mi sembra risieda sul server)...
Nel manuale di Delphi fa appunto un esempio del genere ed indica come piu'
conveniente  impostare manualmente la PrivateDir ad una cartella del PC
locale prima di aprire il database.
E dice pure di non impostare mai la directory principale di un drive, ma
specificare una subdirectory.


 Punta a C:, quindi non dovrebbe dare problemi.
In teoria dovrebbe puntare ad un percorso comune a tutti i client, quindi
una cartella del tuo file server.


 riceve richieste e quindi tutta l'elaborazione è a carico del PC client
Hai colto nel segno. In generale utilizzo veramente poco database Paradox,
quindi non ho mai approfondito questioni di performance con quel sistema
DBMS.
Volevo fornire indicazioni generali, ma nel caso specifico, dopo aver
riflettuto sulle tue indicazioni, temo di essere stato controproducente
:-((
	Marco

:-((
In realta', ogni spunto, ogni riflessione, ogni idea, concorre alla ricerca
della soluzione. :-)
(soluzione che vedo assai lontana, con conseguente frustrazione professionale
e insani sentimenti nei confronti di Borland che ha mantenuto in vita pur non
supportandolo piu' questa panacea del passato. fine dello sfogo... ;-))
Ciao


specificare una subdirectory.
Infatti di default assume la directory dove risiede il programma.
Oltre questo, fai conto che tutti i clients sono win2k. (niente xp)
Any Idea? Intanto provo a eliminare un filtro sulle righe ordine sostituendolo
da una query.
per chi fosse interessato alla funzione di log da eventualmente riutilizzare,
eccola qui:
------------------------------------------------------------------------
uses bde;
procedure TfrmMain.LogBDEEnv;
const
  InfoStr = 'Name: %s'#13#10'Number of sessions: %d'#13#10 +
    'Working directory: %s'#13#10'Language: %s';
var
  Lista : TStringList;
  SysConfigInfo: BDE.SYSConfig;
  sysInfo: BDE.SYSInfo;
  ClientInf: BDE.ClientInfo;
begin
  Lista := TStringList.Create;
  try
     // sysconfig
     Check(DbiGetSysConfig(SysConfigInfo));
     if SysConfigInfo.bLocalShare then Lista.Add('Local Share: ON')
                                  else Lista.Add('Local Share: OFF');
     Lista.Add('Net Protocol: ' + IntToStr(SysConfigInfo.iNetProtocol));
     if SysConfigInfo.bNetShare then Lista.Add('Net Share: ON')
                                else Lista.Add('Net Share: OFF');
     Lista.Add('Network Type: ' + StrPas(SysConfigInfo.szNetType));
     Lista.Add('User Name: ' + StrPas(SysConfigInfo.szUserName));
     Lista.Add('Ini File: ' + StrPas(SysConfigInfo.szIniFile));
     Lista.Add('Language Driver: ' + StrPas(SysConfigInfo.szLangDriver));
     // sysinfo
     Check(DbiGetSysInfo(sysInfo));
     with Lista do begin
        Add(Format('BUFFER SPACE=%d', [sysInfo.iBufferSpace]));
        Add(Format('HEAP SPACE=%d',   [sysInfo.iHeapSpace]));
        Add(Format('DRIVERS=%d',      [sysInfo.iDrivers]));
        Add(Format('CLIENTS=%d',      [sysInfo.iClients]));
        Add(Format('SESSIONS=%d',     [sysInfo.iSessions]));
        Add(Format('DATABASES=%d',    [sysInfo.iDatabases]));
        Add(Format('CURSORS=%d',      [sysInfo.iCursors]));
     end;
     // Client Info
       Check(DbiGetClientInfo(ClientInf));
     with ClientInf do
        Lista.Add(Format(InfoStr, [szName, iSessions, szWorkDir, szLang]));
     // private dir
     Lista.Add('Private dir='+DM.Database1.Session.PrivateDir);
     // attenzione ICLD users: questo e' un logger. sostituirlo con 
     // funzione che estraggal la stringlist                    
     frmMain.dbg.LogStringList('Environment BDE',Lista);
  finally
     Lista.Free;
  end;
end;
--------------------------------------------------------------------


"Morde" ha scritto nel messaggio
In effetti avevo inteso che, risiedendo l'eseguibile sul server, la
PrivateDir risiedesse appunto lě.
Non vedo informazioni sulla NetDir che, come ti ho indicato, dovrebbe
puntare ad un percorso comune per tutti i client sul server.
Altre idee...
per quanto relativo all'opzione LocalShare di configurazione del BDE, dalla
documentazione sembra debba essere impostato a True solo nella
configurazione del BDE sul server (se questo č presente).
Dal 
http://www.bdesupport.com
 mi sembra di ricordare di aver letto che
sarebbe piu' performante utilizzare come protocollo di rete il NetBeui al
posto del TCP/IP... ma non riesco a confermalo perchč non mi apre il sito.
Io personalmente sono passato piu o meno ovunque al TPC/IP (tranne dove ho
dei vecchi win95) e non ho notato niente (devo anche dire che sono cambiati
i PC, quindi praticamente non fa testo).
A logica TTable ed OnFilterRecord sono molto piu' perfomanti (non passa
attraverso l'interprete SQL) sia di TQuery che di TTable con Filter
impostato.
Non credo sia necessario ricordarti di provare con Prepare...
Pensando all'istruzione SQL, proverei a valutare sei la lentezza č dovuta
alla mole di dati o ad un'elaborazione degli stessi legata ad una ORDER BY o
ad una WHERE particolarmente pesanti. In questo caso potresti valutare di
semplificare la query ed effettuare una prima importazione in locale, con
successiva rielaborazione (ma questo dipende da cosa ci devi fare con i dati
estratti).
Ultima altra soluzione, valida ed abbastanza semplice da implementare se i
dati sono in sola lettura, costruire un programmino server da installare sul
server che si occupi dell'estrazione dei dati, predisponendo un flusso
temporaneo da leggere con la tua applicazione sul client. Qualcosa tipo:
- dal client attivi la richiesta;
- il server predispone una tabellina temporanea, mentre dal client attendi
il completamento;
- quando il server ha completato la richiesta leggi la tabellina temporanea.
Questo, a mio avviso, puň rivelarsi molto performante in situazioni dove la
base dati č molto ampia ed il programma deve estrarre una piccola
percentuale di dati (intorno al 10%).
Altro... non saprei. Ho finito tutte le risorse :-)


Altro... non saprei. Ho finito tutte le risorse :-)
Ecco, torno ora a popolare questo thread dopo un mese.
Ho risolto, e questo e' un gran bene per me e per il mio lavoro, ovviamente al
primo posto metto i ringraziamenti verso tutti coloro che mi hanno aiutato a
lavorare su questo problema.
Siccome usando l'alias BDE in rete dal cliente ottenevo dei lag da 1 a 6
secondi, dopo attente prove di verifica dell'infrastruttura della lan, e
accertato che il problema fosse proprio nel programma che accede ai dati, sono
riuscito a parlare con una programmatrice che sviluppa il gestionale.
La soluzione e' stata nel NON utilizzare l'alias BDE ed eliminare per quanto
possibile le query. Mi e' stato raccomandato di utilizzare le primitive
gotokey,gotonearest per le ricerche al posto della locate; e setrange al posto
della proprieta' Filter.
Ora, avendo disseminato di misurazioni le varie locate e sql sulla stessa
tabella, ho accertato che i tempi si sono drasticamente ridotti: da 5,6
secondi a 15 millisecondi (!).
Tutto questo eliminando le Locate e le tquery con select..
Le tabelle sono DBF assai corposi, minimo 60mila record, con indici multipli
MDX.
Concludo con un GRAZIE per l'aiuto a tutti quelli che hanno alimentato il
thread.
Ciao
