Discussione:
Ancora interbase in rete
(troppo vecchio per rispondere)
A
2004-09-01 09:55:07 UTC
Permalink
Ciao a tutti.
Risolti i problemi che avevo riscontrato con l'utilizzo delle transazioni,
mi sto cimentando ora in un passo di sviluppo successivo.
Dopo aver letto un po' di articoli, infatti, sono giunto alla conclusione
che alcune operazioni di gestione dati (generazioni chiave primaria,
inserimento, update e delete) andrebbero gestite a livello del server.
Vi pongo allora le seguenti domande:
1) Il mio ragionamento è corretto?
2) Se così fosse, è meglio utilizzare stored procedures per tutte queste
operazioni o (almeno nel caso della generazione della chiave primaria) è
meglio utilizzare dei generators?
Grazie, e buon lavoro.
A.
Gabriele Santomaggio [W]
2004-09-01 10:13:22 UTC
Permalink
Post by A
Ciao a tutti.
Ciao.
[CUT]
Post by A
conclusione che alcune operazioni di gestione dati (generazioni
chiave primaria, inserimento, update e delete) andrebbero gestite a
livello del server.
1) Il mio ragionamento è corretto?
2) Se così fosse, è meglio utilizzare stored procedures per tutte
queste operazioni o (almeno nel caso della generazione della chiave
Sei pazzo??:)) cioè vuoi farti per ogni operazione una storprocudure e
passargli i dati????
e perchè??? quando fai un semplice ApplyUpdate e ci pensa MIDAS (o chi per
lui ) a fare il tutto???
Post by A
primaria) è meglio utilizzare dei generators?
Scuole di pensiero i generators per me vanno utilizzati stanno lì a
posta....
Da qualche parte sono stato costretto ad utilizzare l'orrendo select MAX+1
form tabella... lato client.
Post by A
Grazie, e buon lavoro.
A.
Ciao
Gabriele
Riccardo
2004-09-01 10:27:22 UTC
Permalink
Post by Gabriele Santomaggio [W]
[CUT]
Da qualche parte sono stato costretto ad utilizzare l'orrendo select MAX+1
form tabella... lato client.
Perchè orrendo (con i dovuti indici impostati sulla tabella) ???

Se lo utilizzassi lato client con una bella stored procedure ?
Sarebbe meno orrendo, no ?

Ciao,
Riccardo
---
Gabriele Santomaggio [W]
2004-09-01 10:31:16 UTC
Permalink
Post by Riccardo
Perchè orrendo (con i dovuti indici impostati sulla tabella) ???
Se lo utilizzassi lato client con una bella stored procedure ?
Sarebbe meno orrendo, no ?
Forse mi sono spiegato male... mi hanno fatto calcolare il codice della
chiave primaria in locale..
quindi se hai due client che inseriscono rischi di andare in keyViolation
cosa che con i GEnarator
non accade perchè la chiave viene generata dal server e viene quindi
garantita l'univocità dell'ID.

Per me è orrendo perchè tutti i DB (o almeno quelli che conosco io..) hanno
strumenti di generazioni delle
chiavi sequenze generator ecc.... e magari ci sarà un perchè li hanno
fatti.
Post by Riccardo
Ciao,
Riccardo
CIao
Gabriele
Riccardo
2004-09-01 14:24:08 UTC
Permalink
Post by Gabriele Santomaggio [W]
Post by Riccardo
Perchè orrendo (con i dovuti indici impostati sulla tabella) ???
Se lo utilizzassi lato client con una bella stored procedure ?
Sarebbe meno orrendo, no ?
Forse mi sono spiegato male... mi hanno fatto calcolare il codice della
chiave primaria in locale..
Ho capito
Post by Gabriele Santomaggio [W]
quindi se hai due client che inseriscono rischi di andare in keyViolation
cosa che con i GEnarator
Certo... è una problematica che ho affrontato proprio in questi giorni con
Firebird.
Post by Gabriele Santomaggio [W]
non accade perchè la chiave viene generata dal server e viene quindi
garantita l'univocità dell'ID.
Esattamente... io comunque mi sono ritrovato costretto a fare una cosa mista
del tipo fare riferimento al GENERATOR sul server ma dal lato client per
ricavare localmente la chiave primaria... ovvimanente il GENERATOR viene
incrementato comunque e dunque non ci sono rischi di key violation.
Post by Gabriele Santomaggio [W]
Per me è orrendo perchè tutti i DB (o almeno quelli che conosco io..) hanno
strumenti di generazioni delle
chiavi sequenze generator ecc.... e magari ci sarà un perchè li hanno
fatti.
Certo che si... ok, allora siamo d'accordo.
Post by Gabriele Santomaggio [W]
Post by Riccardo
Ciao,
Riccardo
CIao
Gabriele
Ciao,
Riccardo

P.S.
Visto che lavori con Interbase, non è che sapresti rispondere
anche al mio post del 31/08 "Lunghezza di una stringa in Firebird" ?
Marco Bortolani
2004-09-01 16:19:42 UTC
Permalink
Post by Riccardo
Esattamente... io comunque mi sono ritrovato costretto a fare una cosa mista
del tipo fare riferimento al GENERATOR sul server ma dal lato client per
ricavare localmente la chiave primaria... ovvimanente il GENERATOR viene
incrementato comunque e dunque non ci sono rischi di key violation.
E' un metodo interessante ma rischioso: se l'utente annulla l'inserimento,
il codice viene perduto... se tu dovessi numerare le fatture, non sarebbe
bello :-((

Ops, però se esegui tutto in una routine questo problema non ce l'hai:
raccogli i dati dall'utente, poi in un colpo solo generi la chiave ed
effettui l'inserimento, restituendo all'operatore il codice appena
utilizzato. Non male :-))

Saluti
Marco Bortolani
info @ marcobortolani.it
Riccardo
2004-09-01 17:49:46 UTC
Permalink
Post by Marco Bortolani
Post by Riccardo
Esattamente... io comunque mi sono ritrovato costretto a fare una cosa mista
del tipo fare riferimento al GENERATOR sul server ma dal lato client per
ricavare localmente la chiave primaria... ovvimanente il GENERATOR viene
incrementato comunque e dunque non ci sono rischi di key violation.
E' un metodo interessante ma rischioso: se l'utente annulla l'inserimento,
il codice viene perduto... se tu dovessi numerare le fatture, non sarebbe
bello :-((
Esattamente, infatti non lo utilizzo per numerare le fatture, ma per
generare
il mio NumReg che poi mi serve per mettere in relazione "master-details"
l'intestazione (MovH) del movimento con le rispettive righe (MovR).

Come avrai intuito però c'è un problema.... ogni volta che un utente annulla
un inserimento in corso il NumReg va comunque avanti perchè anche se
effettuo
un commit della transazione il valore del generator rimane incrementato di
uno.

Ti chiederai perchè succede tutto ciò... beh, perchè avendo una relazione
"master-details" tra MovH e MovR mediante il campo NumReg, in fase
di inserimento di un nuovo movimento, per poter inserire una riga (un
record MovR) sono costretto ad effettuare preventivamente il post del
record di testata (record MovH) per far sì che l'inserimento del record
MovR (collegato con una Foreign Key su NumReg a MovH) non mi
provochi una violazione del vincolo sulla FK poichè non trova nessun
record MovH con il NumReg corrispondente a MovR.NumReg, essendo
tale record MovH ancora non presente sul server ma solo sul client.

Spero di essere stato chiaro... non è che esiste un modo diverso
di aggirare il problema relativo alla violazione del vincolo FK?
Post by Marco Bortolani
raccogli i dati dall'utente, poi in un colpo solo generi la chiave ed
effettui l'inserimento, restituendo all'operatore il codice appena
utilizzato. Non male :-))
Beh... si in questo caso funziona a meraviglia.
Post by Marco Bortolani
Saluti
Marco Bortolani
Ciao,
Riccardo
---
Alberto Salvati
2004-09-02 08:21:44 UTC
Permalink
Post by Marco Bortolani
E' un metodo interessante ma rischioso: se l'utente annulla l'inserimento,
il codice viene perduto... se tu dovessi numerare le fatture, non sarebbe
bello :-((
Usando un select max credo lo avresti comunque.
Già in passato si è parlato di questo argomento.
Per casi assimilabili a quello delle fatture io protendo per una tabella
di contatori il cui accesso è incapsulato in una stored procedure alla
quale si passano come parametri dei valori che saranno usati come chiave
per un SELECT... FOR UPDATE.
Poi, lato app, si richiama questa stored procedure non sulla
OnNewRecord, comoda se ne freghi che nella numerazione vi siano buchi,
ma nella beforeupdate, vincolandola ad un check sullo stato del dataset
che deve ovviamente essere dsInsert.

AS
Alberto Salvati
2004-09-02 08:16:42 UTC
Permalink
Post by Riccardo
Perchè orrendo (con i dovuti indici impostati sulla tabella) ???
anche con gli indici, lo vedo decisamente + lento rispetto all'uso di un
trigger basato su un generator.
Post by Riccardo
Se lo utilizzassi lato client con una bella stored procedure ?
Sarebbe meno orrendo, no ?
Non credo ottimizzi più di tanto: una query di quel genere restituisce
al massimo un record, quindi la maggior parte della ottimizzazione che
ottieni delegando al server, ovvero, la riduzione del traffico di rete
dovuto all'invio dei dati di un cursore dal server al client, te la perdi.

AS
Riccardo
2004-09-02 13:20:20 UTC
Permalink
Post by Alberto Salvati
Post by Riccardo
Perchè orrendo (con i dovuti indici impostati sulla tabella) ???
anche con gli indici, lo vedo decisamente + lento rispetto all'uso di un
trigger basato su un generator.
Beh... sicuramente... non intendevo dire che fosse da paragonare al
generator.
Post by Alberto Salvati
Post by Riccardo
Se lo utilizzassi lato client con una bella stored procedure ?
Sarebbe meno orrendo, no ?
Non credo ottimizzi più di tanto: una query di quel genere restituisce
al massimo un record, quindi la maggior parte della ottimizzazione che
ottieni delegando al server, ovvero, la riduzione del traffico di rete
dovuto all'invio dei dati di un cursore dal server al client, te la perdi.
E' molto interessante quello che dici...
Vista la tua esperienza (senz'altro maggiore della mia)
potresti spiegarmi meglio quest'ultimo passaggio ?

Grazie
Marco Bortolani
2004-09-03 04:46:10 UTC
Permalink
Post by Riccardo
Post by Alberto Salvati
Non credo ottimizzi più di tanto: una query di quel genere restituisce
al massimo un record, quindi la maggior parte della ottimizzazione che
ottieni delegando al server, ovvero, la riduzione del traffico di rete
dovuto all'invio dei dati di un cursore dal server al client, te la perdi.
E' molto interessante quello che dici...
Vista la tua esperienza (senz'altro maggiore della mia)
potresti spiegarmi meglio quest'ultimo passaggio ?
In pratica: premetto un'ovvietà, cioè che, nella programmazione di
un'applicazione database in client/server, le operazioni sui dati le
possono fare il client o il server. Se le operazioni le effettua il client,
sulla rete viaggiano tutti i dati relativi all'operazione da effettuare; se
la stessa operazione viene delegata al server DBMS, sulla rete viaggiano
solamente i risultati dell'elaborazione.

Per farti un esempio: se volessi fare una routine che scorre tutti i record
di una tabella per valutare quello con chiave maggiore (senza utilizzare la
select max), lo potresti fare con una query lato client oppure con una
stored procedure, che viene eseguita lato server e ritorna solamente il
risultato:
LATO CLIENT:
Query1.Text := 'select * from TABELLA';
Query1.Open;
Query1.First;
dato := -MAXINT;
while not Query1.Eof do
begin
if Query1.FieldByName('DATO').AsInteger > dato then
dato := Query1.FieldByName('DATO').AsInteger;
Query1.Next
end;
LATO SERVER (db Interbase)
create procedure SPMAXDATO
returns (
datomax integer)
as
declare datotemp integer;
begin
datomax = -1000;
for select DATO from TABELLA into :datotemp do
begin
if (datotemp > datomax) then
datomax = datotemp;
end;
suspend;
end;
e lato client
Query1.Text := 'select datomax from SPMAXDATO';
Query1.Open;

Questi sono due modi di fare la stessa cosa: il primo però carica di lavoro
il client, il secondo il server: la singola operazione nel secondo caso
risulta quindi effettuata più velocemente, a discapito però delle
prestazioni del sistema globale che risente della maggiore occupazione del
server database, il quale durante l'elaborazione non può "servire" gli
altri client.

Da usare quindi con criterio.

Saluti
Marco Bortolani
info @ marcobortolani.it
Riccardo
2004-09-03 07:41:18 UTC
Permalink
Post by Marco Bortolani
Post by Riccardo
Post by Alberto Salvati
Non credo ottimizzi più di tanto: una query di quel genere restituisce
al massimo un record, quindi la maggior parte della ottimizzazione che
ottieni delegando al server, ovvero, la riduzione del traffico di rete
dovuto all'invio dei dati di un cursore dal server al client, te la perdi.
E' molto interessante quello che dici...
Vista la tua esperienza (senz'altro maggiore della mia)
potresti spiegarmi meglio quest'ultimo passaggio ?
In pratica: premetto un'ovvietà, cioè che, nella programmazione di
un'applicazione database in client/server, le operazioni sui dati le
possono fare il client o il server. Se le operazioni le effettua il client,
sulla rete viaggiano tutti i dati relativi all'operazione da effettuare; se
la stessa operazione viene delegata al server DBMS, sulla rete viaggiano
solamente i risultati dell'elaborazione.
Certo, questo è molto chiaro.... come dici tu una "ovvietà".
Post by Marco Bortolani
Per farti un esempio: se volessi fare una routine che scorre tutti i record
di una tabella per valutare quello con chiave maggiore (senza utilizzare la
select max), lo potresti fare con una query lato client oppure con una
stored procedure, che viene eseguita lato server e ritorna solamente il
Query1.Text := 'select * from TABELLA';
Query1.Open;
Query1.First;
dato := -MAXINT;
while not Query1.Eof do
begin
if Query1.FieldByName('DATO').AsInteger > dato then
dato := Query1.FieldByName('DATO').AsInteger;
Query1.Next
end;
LATO SERVER (db Interbase)
create procedure SPMAXDATO
returns (
datomax integer)
as
declare datotemp integer;
begin
datomax = -1000;
for select DATO from TABELLA into :datotemp do
begin
if (datotemp > datomax) then
datomax = datotemp;
end;
suspend;
end;
e lato client
Query1.Text := 'select datomax from SPMAXDATO';
Query1.Open;
Questi sono due modi di fare la stessa cosa: il primo però carica di lavoro
il client, il secondo il server: la singola operazione nel secondo caso
risulta quindi effettuata più velocemente, a discapito però delle
prestazioni del sistema globale che risente della maggiore occupazione del
server database, il quale durante l'elaborazione non può "servire" gli
altri client.
Da usare quindi con criterio.
Saluti
Marco Bortolani
Beh, sono tutti concetti molto chiari... solo che prima non avevo capito
bene
il senso della tuo concetto riportato in alto, che però adesso mi risulta
più chiaro.

Ciao,
Riccardo
---

P.S.
Ti ho scritto anche in privato... penso avrai già letto la mia email.
Alberto Salvati
2004-09-01 10:59:50 UTC
Permalink
Post by A
Dopo aver letto un po' di articoli, infatti, sono giunto alla conclusione
che alcune operazioni di gestione dati (generazioni chiave primaria,
inserimento, update e delete) andrebbero gestite a livello del server.
1) Il mio ragionamento è corretto?
vi sono vari modi x generare una pk.
Se usi un generator il valore viene calcolato dal server, ma potrebbero
esistere esigenze particolari dove la pk viene generata dalla applicazione.

Riguardo insert, update e delete, queste sono sempre fatte lato server;
che poi usi una query del tipo "INSERT INTO" o una stored procedure che
fa la stessa insert, la app si limita ad assegnare i parametri
all'oggetto e passare il tutto al server.

Dove, in termini di prestazioni, conviene delegare al server?
Nelle elaborazioni pesanti.
Ad esempio, devi consolidare dei totali su una tabella di 5.000.000 di
records? Farlo con una stored procedure risulta in genere più veloce,
sopratutto per l'ovvia riduzione del traffico di rete.

Lo svantaggio è che un approccio basato su stored procedure porta di
fatto parte della logica nel database stesso, quindi ti trovi ad avere
parte di essa nella app e parte nel db.
Questo, ad esempio, è in totale contraddizione allo sviluppo MDA (vedi
modello eco di delphi8 o c#builder) che mette tutta la logica nella app,
usando il database come semplice storage passivo che si limita ad
eseguire operazioni din insert, update, delete e select: basta.

Ancora, se l'elaborazione è *veramente pesante e lunga*, potrebbe
rallentare di molto le altre operazioni eventualmente in corso, cosa che
una applicazione mda non provoca in quanto l'elaborazione viene fatta
lato client e il server si limita a fornire un cursore, magari
unidirezionale.
Post by A
2) Se così fosse, è meglio utilizzare stored procedures per tutte queste
operazioni o (almeno nel caso della generazione della chiave primaria) è
meglio utilizzare dei generators?
le due cose non sono alternative.
Una stored procedure potrebbe essere usata per calcolare un id tramite
un generator.

AS
Continua a leggere su narkive:
Loading...