PDA

View Full Version : [Database] Come usare correttamente le view?


Johnn
15-05-2010, 14:34
Scenario (penso classico):
una o più tabelle con molti campi;
l'applicazione ha bisogno di accedere ad uno o più sottoinsiemi di questi campi.

Per prima cosa si devono nascondere i campi come l'ID, chiavi esterne, ecc. anche per ragioni di sicurezza immagino.
Dei campi rimanenti, spesso serve solo un sottoinsieme e/o un sottoinsieme di tuple (clausola WHERE).

Cosa è meglio fare? Una vista ad hoc per ogni sottoinsieme oppure una vista con i tutti i campi accessibili per l'applicazione e poi di volta in volta estrarre i campi necessari?

Esempio:
campo_ 1 (id), campo_2, campo_3, campo_4

Soluzione 1:
View_1: campo_2, campo_3
View_2: campo_3, campo_4
_____________________________
Soluzione 2:
View: campo_2, campo_3, campo_4

SELECT campo_2, campo_3 FROM View;
SELECT campo_3, campo_4 FROM View;

In entrambi i casi si dovrebbe comunque lanciare un'ulteriore query di volta in volta che incorpori le eventuali condizioni (WHERE).

Ci sono altre, soluzioni anche sostanzialmente diverse, ma che avrebbero qualche vantaggio? (Non so, per esempio i tipi custom...).

Grazie.

Johnn
17-05-2010, 14:37
UP!

Johnn
20-05-2010, 12:54
Da quanto ho letto un po' in rete le quotazioni delle view sono in discesa. :D Le procedure permettono di mascherare la reale struttura del db in maniera analoga.
Sono ancora utili in certi casi dove si vuole mostrare solo parte del db in base a permessi e per la manutenzione del codice (per evitare numerosi cambiamenti in tante procedure).

Non sono riuscito ancora a trovare però una risposta al primo post.

deadlyomen17
20-05-2010, 13:28
le view vanno usate con molta cautela e cognizione di causa.

il problema fondamentale delle view è l'aggiornamento.

se hai una view definita su due tabelle, cosa succede quando aggiorni una di queste tabelle, la view si aggiorna anche? e se invece aggiorni la view l'aggiornamento si deve ripercuotere anche sulle tabelle di partenza? e se ci sono constraint?

tutti questi problemi hanno portato alla decisione di non rendere le view aggiornabili (a parte nel caso in cui queste siano definite su un'unica tabella e contengano i campi chiave primarie e non contengano chiavi esterne...)

inoltre il vero punto forte delle view non è certo il fatto che si possano nascondere alcuni campi etc, bensì il fatto che AUMENTANO il potere espressivo di SQL: rendono in pratica possibili alcune interrogazioni che senza l'uso di view sarebbero impossibili.

altro punto di forza (delle view materializzate) è che in queste si può salvare il risultato di una query anche molto costosa, in modo da evitare di rifare la query ogni volta, con enormi vantaggi prestazionali (pensa in un'ottica di decine e centinaia di miliaia di tuple)

quindi è chiaro che l'uso delle view, che da diverse parti porta vantaggi, deve essere ben valutato in vista dei problemi di aggiornamento.

procedure e funzioni non sostituiscono affatto le view, ma portano comunque moltissimi vantaggi

in particolare, per i tuoi scopi (se ho capito bene quali sono) l'uso di procedure è sicuramente più indicato, ma attenzione al fatto che non tutti i DBMS supportano i linguaggi procedurali.

Johnn
20-05-2010, 17:26
inoltre il vero punto forte delle view non è certo il fatto che si possano nascondere alcuni campi etc, bensì il fatto che AUMENTANO il potere espressivo di SQL: rendono in pratica possibili alcune interrogazioni che senza l'uso di view sarebbero impossibili.


In che senso? Quali interrogazioni sarebbero altrimenti impossibili?


altro punto di forza (delle view materializzate) è che in queste si può salvare il risultato di una query anche molto costosa, in modo da evitare di rifare la query ogni volta, con enormi vantaggi prestazionali (pensa in un'ottica di decine e centinaia di miliaia di tuple)


Sapevo questa cosa e la reputo utile nei casi opportuni. Ma per filosofeggiare un po', una vista materializzata indica una cattiva progettazione del db, no? Teoricamente non si dovrebbe mai arrivare ad usarle!?


quindi è chiaro che l'uso delle view, che da diverse parti porta vantaggi, deve essere ben valutato in vista dei problemi di aggiornamento.

procedure e funzioni non sostituiscono affatto le view, ma portano comunque moltissimi vantaggi

in particolare, per i tuoi scopi (se ho capito bene quali sono) l'uso di procedure è sicuramente più indicato, ma attenzione al fatto che non tutti i DBMS supportano i linguaggi procedurali.

Ammettiamo che il DBMS supporti i linguaggi procedurali e che le view siano in sola lettura, quindi nessun problema di aggiornamento.

Perché una procedura non potrebbe sostituire una view?
Se la view è basata sulla query X e si mette la stessa query X in una procedura che restuisce i risultati, con in più la possibilità mediante parametri di essere customizzati tramite la clausola WHERE, che differenze ci sono?

Grazie ancora.

deadlyomen17
20-05-2010, 17:55
In che senso? Quali interrogazioni sarebbero altrimenti impossibili?

ti consiglio di prendere un libro qualsiasi di basi di dati (ovviamente a livello universitario) e studiare li questo argomento.

il momento in cui è più evidente che l'uso di viste aumenta il potere espressivo è quando bisognerebbe far uso di operatori aggregati "a cascata"
esempio:
Dipartimento( cod, nome )
Dipendente( cod, nome, stipendio, dipartimento* )

(* indica un vincolo di integrità referenziale)

si vuole sapere il codice del dipartimento che spende di più per gli stipendi dei suoi impiegati...

fammi questa query senza usare una vista.


Sapevo questa cosa e la reputo utile nei casi opportuni. Ma per filosofeggiare un po', una vista materializzata indica una cattiva progettazione del db, no? Teoricamente non si dovrebbe mai arrivare ad usarle!?

non vedo perchè una vista materializzata debba indicare cattiva progettazione.
anzi, a volte è proprio per avere una logica il più possibile pulita e ben fatta che l'uso delle viste materializzate diventa comodo.
un esempio stupido ma che dovrebbe farti capire:
decido, per tenere i concetti logici ben separati, di fare una tabella account e una persona, nella prima ci sono solo i dati relativi all'account, nell'altra i dati anagrafici della persona.
da notare che si gestiscono milioni di account, e altrettante persone quindi.
nella pratica, per qualche motivo, ho molto spesso bisogno di riportare i dati dell'utente in maniera completa, quindi riportando sia quelli del suo account che quelli anagrafici, quindi sono costretto a fare un join ogni volta, che costa.
un vista materializzata sarebbe una manna dal cielo, in quanto io farei il join soltanto una volta, e salverei il risultato nella vista, e quindi tutte le volte che dovrei accedere ai dati interrogherei direttamente questa vista, senza bisogno di dover rifare il join ogni volta.

ecco, in questo caso, banalissimo e non così reale, si può già intravvedere che fare una progettazione logica pulita e rigorosa mi ha portato questo piccolo problema, che non ci sarebbe stato se avessi progettato il sistema con un'unica tabella che conteneva sia i dati anagrafici che quelli del proprio account.


Ammettiamo che il DBMS supporti i linguaggi procedurali e che le view siano in sola lettura, quindi nessun problema di aggiornamento.

Perché una procedura non potrebbe sostituire una view?
Se la view è basata sulla query X e si mette la stessa query X in una procedura che restuisce i risultati, con in più la possibilità mediante parametri di essere customizzati tramite la clausola WHERE, che differenze ci sono?

Grazie ancora.

proprio perchè inserendo la query X nella procedura, questa query verrà rifatta ogni volta, mentre usando una vista materializzata no.

ti ricordo che le procedure sono vantaggiose in quanto, oltre ad aumentare il potere espressivo, vengono compilate una sola volta, mentre le query standard vengono compilate ogni volta.

ma l'esecuzione viene comunque fatta ogni volta.

PS: i problemi delle view non si risolvono rendendole di sola lettura

gugoXX
21-05-2010, 00:31
proprio perchè inserendo la query X nella procedura, questa query verrà rifatta ogni volta, mentre usando una vista no.
Il motore riesegue lo statement di una vista sempre.
Anche quando eseguita a distanza di pochi secondi.
E anche se i dati sottostanti non sono stati modificati.

Diverso sarebbe per le vista materializzate. Ma quando si parla di viste materializzate l'aggettivo "Materializzate" bisogna metterlo sempre.
Non tutti i DB supportano viste materializzate.
E' vero che le viste materializzate NON sono indice di cattiva progettazione. Anzi, vengono usate per motivi di performance proprio laddove c'e' stata una buona progettazione.

Relativamente ai tempi di compilazione di viste o procedure, non sono piu' influenti da anni.

deadlyomen17
21-05-2010, 10:49
Diverso sarebbe per le vista materializzate. Ma quando si parla di viste materializzate l'aggettivo "Materializzate" bisogna metterlo sempre.


hai perfettamente ragione, lo avevo omesso visto che ne parlavo prima ma in effetti ci va messo; edito il post per evitare di generare confusione anche a chi in futuro leggerà la discussione

Relativamente ai tempi di compilazione di viste o procedure, non sono piu' influenti da anni.

a livello pratico è così ed è noto...ma quando si tratta di uno studio più che altro teorico/metodologico, che credo sia il caso dell'autore del thread, è bene sottolineare anche questo fattore che non è certo una banalità (traduzione, ottimizzazione etc).

Johnn
21-05-2010, 18:36
il momento in cui è più evidente che l'uso di viste aumenta il potere espressivo è quando bisognerebbe far uso di operatori aggregati "a cascata"
esempio:
Dipartimento( cod, nome )
Dipendente( cod, nome, stipendio, dipartimento* )

(* indica un vincolo di integrità referenziale)

si vuole sapere il codice del dipartimento che spende di più per gli stipendi dei suoi impiegati...

Ok, stavo erroneamente pensando all'obbligo di fare una CREATE VIEW in certe situazioni. (Dopo si capirà anche meglio.)


non vedo perchè una vista materializzata debba indicare cattiva progettazione.

Ok.


In effetti ho impostato, sbagliando, troppo la discussione sotto un aspetto teorico. Lavorando su un database mi sono imbattuto nel problema di dover scegliere come presentare i dati all'applicazione, senza voler nè reinventare ruote, nè utilizzare soluzioni astruse. Per questo ho chiesto qui una soluzione generale al problema. Sono ancora interessato alla parte metodologica cioè come si risolve questa cosa normalmente, in generale?

Solo da poco (ieri :D ) mi sono accorto che mi stavo imbattendo in una limitazione dell'DBMS, Postgresql: le funzioni non permettono di restituire insiemi di record arbitrari. I campi devono essere prestabiliti obbligatoriamente. Quindi se ad un certo punto l'applicazione ha bisogno di un nuovo sottoinsieme dei campi di una certa tabella si deve implementare una nuova funzione che restiuisca il nuovo gruppo di campi. Poiché mi pareva una cosa pericolosa pensando in ottica futura e che porta a mettere pezze su pezze, ho cercato un'altra soluzione: pensando che stessi usando lo strumento sbagliato, sono approdato alle viste (intese come CREATE VIEW, non implicite). Ma portava ad altri problemi. E da qui il primo post.

deadlyomen17
21-05-2010, 22:20
le funzioni non permettono di restituire insiemi di record arbitrari. I campi devono essere prestabiliti obbligatoriamente.

non so se ho capito bene ciò che intendi...ma usando "setof record" puoi ritornare un generico record -> Wiki PostgreSQL (http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions)

Sono ancora interessato alla parte metodologica cioè come si risolve questa cosa normalmente, in generale?

in realtà non credo ci sia una regola generale, perchè dipende molto dallo scenario che si considera...
per i tuoi scopi, vedo più opportuno l'uso di procedure o funzioni...

Johnn
21-05-2010, 23:31
non so se ho capito bene ciò che intendi...ma usando "setof record" puoi ritornare un generico record -> Wiki PostgreSQL (http://wiki.postgresql.org/wiki/Return_more_than_one_row_of_data_from_PL/pgSQL_functions)


Sì hai ragione, e avevo pure provato, con successo, quella soluzione. Solo che non mi ha convinto per come deve essere chiamata una funzione con quel tipo di ritorno ( SELECT * FROM f() ), (e me la sono dimenticata rapidamente :asd:).
Magari sbaglierò, ma mi pare di inserire l'sql nell'applicazione. Allora che le uso a fare le funzioni? Anche perché non solo "sporcherei" il sorgente dell'applicazione (e potrebbe essere solo un vezzo), ma poi dovrei comunque stare attento a quale funzione chiamare con SELECT e quale senza.

Che sia un limite che in altri DBMS non c'è l'ho letto da qui:
http://www.postgresonline.com/journal/index.php?/archives/15-Stored-Procedures-in-PostgreSQL.html
Verso la fine si arriva a parlare di questo (Davor vs Regina).


in realtà non credo ci sia una regola generale, perchè dipende molto dallo scenario che si considera...
per i tuoi scopi, vedo più opportuno l'uso di procedure o funzioni...

Potenzialmente, il db può esporre tabelle e viste all'applicazione. Da lì si potrebbero fare le query. Ma ho ritenuto non opportuno disseminare il codice dell'applicazione di SQL, pure se fosse solo confinato in uno strato ad hoc. Però magari mi direte che normalmente si usa SQL puro ovunque per ragioni che a me sfuggono e allora mi adeguerò, quando sarà il caso.

Quindi tutto nelle funzioni e l'applicazione le chiama. Tutto bene fino al caso di un insieme di record. In questo caso le soluzioni sono:
1) creo un tipo per ogni insieme restituito: da un certo punto di vista è la soluzione che mi piace di più, solo che è veramente noisa da implementare: ogni volta crea un nuovo tipo ed usalo magari una sola volta;
2) SETOF RECORD, scritto sopra;
3) usare i parametri OUT: sarei però costretto ad esplicitare tutti i campi tra i parametri delle funzioni e questi potrebbero essere numerosi; se devo aggiungere successivamente un campo devo riscrivere la funzione e tutte le chiamate nell'applicazione;
4) usare le viste che espongono tutti gli insiemi di dati accessibili, ma necessità di usare l'SQL nell'applicazione.