• Non ci sono risultati.

Raggruppamento invariante

6.3 Schemi a fiocco di neve

6.3.1 Raggruppamento invariante

Il caso diraggruppamento invariante su schemi a fiocco di neve pu`o essere “ri- dotto” a quello su schemi a stella, sfruttando la presenza di fiocchi fra gli attributi dimensionali. Considerato che le giunzioni sono sempre di tipo chia- ve esterna-chiave, basterebbe che la tabella dei fatti riferisse il “livello pi`u alto” della gerarchia per determinare automaticamente tutti il livelli del fioc- co. Tornando dunque alla notazione precedentemente introdotta possiamo rappresentare un’interrogazione su schema a fiocco di neve come:

(((F Cj1 D1) Cj2D2) . . . Cjn Dn)

La differenza in questo caso `e che qualche Di `e da interpretare come una

60 CAPITOLO 6. GENERALIZZAZIONE

Di = Di1 Cj1Di2. . . CjmDim (6.1)

se m sono le tabelle del fiocco. Si ricade sostanzialmente nel caso della giunzione per schemi a stella, formalizzando la nozione come:

Proposizione 16 Siano D1, . . . , Dnrelazioni riferite da R tramite le chiavi

esterne{fk1, . . . , fkn} con qualche Digiunzione delle tabelle del fiocco come

in 6.1. L’equivalenza:

AγF(R Cj{D1, . . . , Dn}) ≡ π

b

A∪F((((AR∪α(Cj)−α(D)γF(R)) Cj1D1) . . . CjhDh))

`e valida se:

1. gli attributi di giunzione di R con tabelle dimensionali {D1, . . . , Dh} ⊆

{D1, . . . , Dn} con attributi in A (diversi dalla pk) sono determinati dagli

attributi A di raggruppamento di R Cj {D1, . . . , Dh}

2. gli attributi di aggregazione in F sono attributi di R.

Esempio 11 Si supponga di voler eseguire sulla base di dati:

Ordini(PKord, FKprod*, FKdata*, FKag*, qt, prezzo) Prodotti(PKprod, FKfil*, pNome, costo)

Filiali(PKfil, fNome, FKcitt`a*) Agenti(PKag, aNome, FKcitt`a*) Date(PKdata, giorno, mese, anno) Citt `a(PKcitt `a, cNome, FKprovincia*)

Province(PKprovincia, prNome, FKregione*) Regioni(PKregione, rNome)

l’interrogazione:

SELECT C.cNome, F.fNome, P.pNome, SUM(prezzo) FROM Ordini O, Prodotti P, Filiali F, Citt`a C

WHERE O.FKprod=P.PKprod AND P.FKfil=F.PKfil AND F.FKcitt`a=C.PKcitt`a GROUP BY P.PKprod, C.cNome, F.fNome, P.pNome

Osserviamo che l’interrogazione rispetta le condizioni espresse dalla precente propo- sizione. Infatti l’insieme A `e formato dagli attributi{FKprod,cNome,fNome,pNome}.

6.3. SCHEMI A FIOCCO DI NEVE 61

Notiamo che per come sono formulate le giunzioni l’attributoFKproddiOrdinideter- mina gli altri attributi presenti in A e che gli attributi di raggruppamento determinano quelli di giunzione. Dunque la prima condizione `e rispettata.

Vale poi che gli attributi di aggregazione dell’interrogazione appartengono alla tabella dei fatti.

Infine si pu`o vedere che le tabelleProdotti,Filialie Citt`aformano un fiocco la cui radice `e rappresentata dalla relazione Prodotti. In A c’`e la chiave esterna diOrdini

per la radice di tale fiocco. Tale chiave `e rappresentata dall’attributoFKprod. Si pu`o quindi anticipare il raggruppamento ottenendo il seguente albero logico:

πb

cNome, fNome, pNome, SUM(prezzo)  FKcitt `a=PKcitt`a  FKfil=PKfil Citt `a  FKprod=PKprod Filiali

FKprodγSU M(prezzo) Prodotti

Ordini

6.3.2

Raggruppamento parziale

Estendiamo ora al caso di interrogazioni su schemi a fiocco di neve la pro- priet`a diraggruppamento parziale. Considerando interrogazioni come in sezio- ne 6.1 si ipotizza che gli attributi di raggruppamento non determinino quelli di giunzione; la seguente proposizione fornisce delle condizioni per “spezzare” il raggruppamento anticipando il primo passo sulla tabella dei fatti:

Proposizione 17 Siano D1, . . . , Dnrelazioni dimensionali riferite da R tra-

mite{fk1, . . . , fkn}, A = AR∪ ADi con AR ⊆ α(R), ADi ⊆ α(Di) ∀i, sia

62 CAPITOLO 6. GENERALIZZAZIONE

AγF(R Cj {D1, . . . , Dn}) ≡AγFg(AR∪α(Cj) −α(Di)γFl(R) Cj {D1, . . . , Dn})

se:

1. Gli attributi di aggregazione sono attributi di R 2. F `e un insieme di funzioni decomponibili

Notiamo che le prime due condizioni enunciate per la validit`a della trasfor- mazione possono essere sostituite richiedendo che F contenga funzioni di aggregazione che utilizzano attributi delle relazioni dimensionali e che pos- sono essere calcolate a partire dalla cardinalit`a dei gruppi che si creano sulla tabella dei fatti.

Esempio 12 Si consideri lo schema:

Ordini(PKord, FKprod*, FKdata*, FKag*, qt, prezzo) Prodotti(PKprod, FKfil*, pNome, costo)

Filiali(PKfil, fNome, FKcitt`a*) Agenti(PKag, aNome, FKcitt`a*) Date(PKdata, giorno, mese, anno) Citt `a(PKcitt `a, cNome, FKprovincia*)

Province(PKprovincia, prNome, FKregione*) Regioni(PKregione, rNome)

e l’interrogazione:

SELECT C.cNome, P.pNome, SUM(qt) AS quantit`a FROM Ordini O, Agenti A, Prodotti P, Citt`a C

WHERE O.FKag=A.PKag AND A.FKcitt`a=C.PKcitt`a AND O.FKprod=P.PKprod GROUP BY C.cNome, P.pNome, P.Pkprod

L’interrogazione calcola quanto ogni prodotto sia stato venduto nelle diverse citt`a. Abbiamo visto che per la validit`a della trasformazione `e necessario che l’insieme

AR contenga gli attributi di giunzione fra la tabella dei fatti e la relazione dimen-

sionale radice di un fiocco. In questo caso la relazione Agenti `e radice di un fiocco. L’insieme ARconterr`a sicuramente l’attributo PKag della relazione Agenti.

6.3. SCHEMI A FIOCCO DI NEVE 63

L’altra condizione richiesta, quella relativa alle funzioni di aggregazione, `e che queste siano decomponibili. La funzione SU M(qt), con la semantica espressa nel- l’interrogazione, si pu`o calcolare in pi`u passi purch`e nel primo passo di questi si raggruppi sulla chiave del prodotto stesso. Dunque anche l’attributo PKprod della relazione Prodotti dovr`a essere contenuto nell’ insieme AR.

L’insieme ARsar`a dunque formato dagli attributi{P Kag, P Kprod}. Osserviamo

che AR`e determinato dall’insieme di attributi{F Kag, F Kprod} nella relazione che

si ottiene dalla giunzione fra le tabelle presenti nella clausola FROM. Questo perch`e la giunzione impone un vincolo di uguaglianza fra le chiavi. In realt`a proprio l’ultimo insieme presentato `e l’insieme AR perch`e gode della propriet`a di essere contenuto

nella tabella dei fatti. Il primo insieme presentato come AR `e infatti formato da

attributi appartenenti alle relazioni dimensionali. Un tale ARconsente l’anticipazione

del raggruppamento come segue:

cNome, PKprod, pNomeγSU M(Q1)AS quantit`a

 FKcitt `a = PKcitt`a 

FKProd = PKProd Citt `a

FKprod, FKagγSUM(qt) ASQ1 Prodotti

Ordini

L’albero logico visto `e quello ottenuto con la riscrittura dell’interrogazione come presentata precedentemente. In tale albero sono stati omessi alcuni dei passi di giun- zione fra le tabelle dimensionali e quella dei fatti. L’albero ottenuto da un classico ottimizzatore sarebbe privo del primo passo di raggruppamento. Come sempre, bi- sogna decidere dell’opportunit`a di anticipare o meno il raggruppamento sulla base di molti parametri . I vantaggi che possono scaturire dalla strategia presentata sono tanto maggiori quanto maggiore `e il numero di agenti diversi che vende in una stessa citt`a.

64 CAPITOLO 6. GENERALIZZAZIONE

6.3.3

Raggruppamento e conteggio

L’ultima propriet`a di cui si esamina il comportamento su schemi a stella `e quella diraggruppamento e conteggio. Le ipotesi sono quelle formulate in 5.1. La seguente proprosizione fornisce condizioni che consentono di anticipare il raggruppamento sulla tabella dei fatti.

Proposizione 18 Siano D1, . . . , Dnrelazioni dimensionali riferite da R tra-

mite {fk1, . . . , fkn}, sia inoltre B = BR ∪ BD1, . . . , BDn l’insieme degli

attributi di aggregazione con BR ⊆ α(R), BDi ⊆ α(Di) ∀i; l’equivalenza: AγF(R Cj{D1, . . . , Dn}) ≡ π

b

A∪X(AR∪fkiγH∪count(∗)(R) Cj {D1, . . . , Dn})

`e valida se:

1. A → fki i= 1, . . . , n

2. F = H ∪ G con H un insieme di funzioni di aggregazione con attributi di

R e G un insieme di funzioni di aggregazione{f(ai)} decomponibili che

usano attributi aidi Dj

L’insieme X deve avere la caratteristiche gi`a viste negli altri casi diraggrup- pamento e conteggio.

Esempio 13 Si consideri la base di dati:

Ordini(PKord, FKprod*, FKdata*, FKag*, qt, prezzo) Prodotti(PKprod, FKfil*, pNome, costo)

Filiali(PKfil, fNome, FKcitt`a*) Agenti(PKag, aNome, FKcitt`a*) Date(PKdata, giorno, mese, anno) Citt `a(PKcitt `a, cNome, FKprovincia*)

Province(PKprovincia, prNome, FKregione*) Regioni(PKregione, rNome)

6.3. SCHEMI A FIOCCO DI NEVE 65

SELECT A.ANome. P.pNome, (SUM(O.prezzo)-SUM(P.costo)) AS guadagno FROM Ordini O, Agenti A, Prodotti P, Date D

WHERE O.FKag=A.PKag AND O.FKprod=P.PKprod AND FKData=PKdata GROUP BY O.FKAg, O.FKProd, P.pNome, A.aNome

che calcola quanto ogni agente ha guadagnato dalle vendite del prodotto y nell’anno

x. In questa forma l’interrogazione deve essere risolta effettuando prima la giunzione

fra le relazioni coinvolte e successivamente il raggruppamento ed il calcolo delle funzioni di aggregazione; si ottiene cos`ı:

FKAg, FKProd, aNome, pNomeγSU M(P.prezzo) − SUM(P.costo) AS guadagno

 O.FKag = A.PKag Agenti  O.FKProd=P.PKprod Prodotti Ordini

Nell’albero abbiamo omesso le operazioni di restrizione sulle tabelleProdotti,Date. Il fatto che il raggruppamento avvenga come ultima operazione `e dovuto a due fattori:

– Gli attributi di raggruppamento appartengono alle relazioni dimensionali

– Il calcolo delle funzioni di aggregazione richiede attributi delle tabelle dimensio- nali

In sezione 3.2.4 abbiamo illustrato una tecnica che permette di ovviare al primo dei problemi posti. Per quanto riguarda il secondo osserviamo che in questo caso `e possibile utilizzare un differente algoritmo per calcolare il guadagno. In effetti il valore della funzione SU M(P.costo) pu`o essere ottenuto a con una funzione equi- valente calcolabile a partire dal valore che l’attributoP.costoassume su un’ennupla della tabellaProdotti:

66 CAPITOLO 6. GENERALIZZAZIONE

SU M(P.costo) = COUNT (∗) × P.costo

Osserviamo poi che gli attributi{A.F KAg, O.F Kprod} → {A.aNome, P.pNome}. In base alla regola 2.6 affermiamo che raggruppando sui soli attributi{A.F KAg, O.F Kprod} il risultato dell’operazione `e uguale.

A questo punto, pur rimanendo valido il precedente albero logico, vediamo che se ne ottiene uno migliore anticipando il raggruppamento e calcolando le funzioni di aggregazione immediatamente. Il valore del guadagno sar`a ottenuto solo nell’ ultima parte dell’interrogazione grazie ad un’espressione algebrica che si risolve al momento della proiezione. L’albero `e

πA.aNome, P.pNome,b (SUM(P.prezzo) − (GBCOUNT ∗ P.costo)) AS guadagno 

O.FKAg = A.PKAg 

O.FKProd = P.PKProd Agenti

Prodotti

FKAg, FKProdγSU M(P.prezzo), COUNT (∗)AS GBCOU N T

Ordini

6.4

Clausola HAVING

L’operazione di raggruppamento prevede un costrutto HAVING che consente di specificare condizioni cui i gruppi creati devono uniformarsi; tali condizio- ni possono essere raltive alla cardinalit`a dei gruppi stessi cos`ı come possono essere condizioni relative al valore che le funzioni di aggregazione assumono sui diversi gruppi. In entrambi i casi quello che si vuole ottenere `e un con- trollo sui gruppi creati specificando delle condizioni di “ammissibilit`a”. Nelle prossime sezioni esamineremo interrogazioni del tipo:

SELECT AR, AD, F(B)

6.4. CLAUSOLAHAVING 67

WHERE Cj

GROUP BY AR, ADi

HAVING Chaving

con l’intento di capire in quali casi sia possibile valutare la condizione Chaving

prima di proseguire nella valutazione degli altri operatori che compaiono nel- l’albero logico. Lo scopo, come sempre,`e quello di ridurre la dimensione dei risultati intermedi, traendo beneficio nella risoluzione dell’interrogazione.

Rappresenteremo in algebra quest’interrogazione con:

σChaving(AγF(B)(R CjD))

e faremo l’ipotesi che σChaving sia una restrizione che non interessa gli attributi

in A.

6.4.1

Raggruppamento invariante

Per quanto riguarda il raggruppamento invariante abbiamo visto, nelle sezioni precedenti, che questa trasformazione, per quanto soggetta a vincoli molto forti, `e quella che consente di “lasciare” quasi del tutto invariata, la forma dell’interrogazione. Come conseguenza si ha che il valore che le funzioni di aggregazione assumono `e calcolato contestualmente alla creazione del gruppo ed il calcolo avviene in un unico passo. La condizione Chaving `e valutabile

immediatamente dopo la creazione del gruppo, stabilendo cos`ı se tale gruppo “ha diritto” o meno di andare in giunzione con le altre relazioni.

6.4.2

Raggruppamento parziale

Nel caso diraggruppamento parziale `e necessario attendere la fine del calco- lo delle funzioni di aggregazione e quindi l’applicazione delle Fg (funzioni

globali) ai gruppi creati nei precedenti raggruppamenti. Esiste in ogni caso un’eccezione alla regola di valutazione della clausola HAVING ed `e quella in cui questa specifichi una condizione sulla cardinalit`a dei gruppi che si creano: qualora si volesse che i gruppi non superino un valore soglia v e tale valore sia stato superato nel primo dei raggruppamenti per qualche gruppo. Ricordiamo che la coppia di funzioni (locale e globale) in cui si decompone la funzio- ne COU N T(∗) `e la coppia ((COUNT (∗), SUM(COUNT (∗))). Quindi,

68 CAPITOLO 6. GENERALIZZAZIONE

se il valore calcolato dalla prima delle due `e superiore a v il gruppo pu`o es- sere eliminato evitando di effettuarne la giunzione. Questo pu`o avvenire a patto di scartare tutti i gruppi che, nei successivi raggruppamenti, sarebbero convogliati i un unico gruppo assieme a quello che viene scartato.

In realt`a, formulando ipotesi pi`u dettagliate sul tipo di funzioni che si cal- colano, sulla restrizione imposta dalla clausola HAVING nonch`e sul dominio dei valori su cui variano gli attributi di aggregazione `e possibile stabilire una precisa casistica sull’anticipazione della restrizione:

– Se f `e SU M(a), dom(a) = x (x > 0) e σ `e SUM(a) < v la clausola pu`o essere valutata dopo il primo dei raggruppamenti.

– Se f `e SU M(a), dom(a) = x (x < 0) e σ `e SUM(a) > v la clausola pu`o essere valutata dopo il primo dei raggruppamenti.

– Se f `e COU N T(∗), σ `e COUNT (∗) < v la valutazione pu`o essere anticipata come sopra.

Si precisa che la valutazione anticipata della clausola dopo il primo rag- gruppamento non esclude che questa venga valutata anche dopo il comple- tamento dell’ultimo dei raggruppamenti. In altre parole, se la propriet`a di raggruppamento invariante ci permette di effettuare la riscrittura:

(AγF(B)(R Cj D)) ≡AγFg(B)(AγFl(B)(R) Cj D)

allora rappresentiamo la clausola HAVING come:

σChaving(AγFg(B)(AγFl(B)(R) Cj D))

e dunque la riscrittura che si effettua `e:

σChaving(AγF(B)(R Cj D)) ≡ σChaving(AγFg(B)(σφ(σChaving(AγFl(B)(R)) CjD))

dove φ `e una condizione del tipo(A = x) con x che varia sul dominio dei valori dei gruppi “scartati” nel primo dei raggruppamenti.

6.4.3

Raggruppamento e conteggio

La clausola HAVING deve essere valutata necessariamente alla fine del calco- lo delle funzioni di aggregazione e dunque al completamento dell’operazione di giunzione.

Capitolo 7

CONCLUSIONI

Nel presente lavoro sono state analizzate le propriet`a di raggruppamento in-

variante, raggruppamento parziale e raggruppamento e conteggio. Tali pro-

priet`a consentono l’anticipazione dei raggruppamenti rispetto alle giunzio- ni nell’esecuzione di interrogazioni SQL. L’obbiettivo di tali trasformazio- ni `e quello di ridurre la dimensione dei risultati intermedi con conseguente riduzione del costo di esecuzione dell’interrogazione.

L’analisi delle propriet`a citate `e avvenuta sulla base di propriet`a associa- te ai singoli operatori relazionali che possono comparire nella traduzione di un’interrogazione SQL in un’espressione dell’algebra. Sfruttando le propriet`a composizionali degli operatori relazionali si sono ottenute dimostrazioni di condizioni necessarie e sufficienti per l’anticipazione del raggruppamento nei tre casi presentati. Questi sono fra quelli che ricorrono pi`u spesso nelle query a stella. L’analisi, basata sul formalismo dell’algebra, ci ha consentito di gene- ralizzare i risultati ottenuti per il caso bidimensionale al caso n-dimensionale in maniera relativamente facile. Ci ha inoltre consentito di astrarre da molti dettagli relativi al calcolo del risultato di un’interrogazione SQL. Un ulteriore vantaggio che scaturisce dal formalismo adottato `e quello di raccogliere ca- ratteristiche comuni a tutti gli altri formalismi adottati dagli altri autori; solo cos`ı `e stato possibile avere una visione di insieme dei diversi risultati raggiun- ti da questi ultimi. In effetti, negli altri lavori analizzati, si `e constatato che i formalismi adottati sono basati su un approccio differente. Tale approccio rende piuttosto pesante la trattazione di alcune delle propriet`a analizzate favo- rendo quella di altre. Altrettanto vero `e che tali formalismi sono stati pensati in alcuni casi per favorire il calcolo su n-uple contententi valori nulli, in altri per favorire il calcolo delle funzioni di aggregazione. La trattazione risulta

70 CAPITOLO 7. CONCLUSIONI

essere pi`u diretta e concisa laddove ricorrono tali situazioni consentendo la costruzione di un algoritmo in grado di valutare la possibilit`a di anticipare o meno il raggruppamento.

Infine, nel generalizzare i risultati al caso n-dimensionale, l’enfasi `e sta- ta posta sulla possibilit`a, da parte dell’ottimizzatore, di decidere immedia- tamente se sia possibile o meno anticipare il raggruppamento sulla tabel- la dei fatti. Dal momento che nell’ottimizzazione di un’interrogazione n- dimensionale lo spazio delle soluzioni che si esplora `e vasto, il costo di ta- le esplorazione diventa in alcuni casi proibitivo. L’ottimizzatore `e invece in grado di valutare immediatamente la validit`a delle condizioni individua- te in questo lavoro isolando parzialmente il problema dell’ottimizzazione ad un’analisi delle caratteristiche degli attributi delle relazioni che compaiono nell’interrogazione.

Bibliografia 71

Bibliografia

[AAC] A. ALBANO, Costruire Sistemi per Basi di Dati, Addison Wesley, 2001.

[ABSD] A. ALBANO, Appunti di Basi di dati di supporto alle decisioni, 2007.

[AGOB] A. ALBANO, G. GHELLI, R. ORSINI, Fondamenti di basi di dati, Zanichelli, 2005.

[CSO] S. CHAUDHURI, K. SHIM, Including Group-By in Query Optimi- zation, in: Proceedings of the 20st VLDB Conference Santiago, Chile, 1994.

[GJM] C. A. GALINDO LEGARIA, M. M. JOSHI, Orthogonal Optimiza- tion of Subqueries and Aggregation, in: Proceedings of ACM SIGMOD, Santa Barbara, California, 2001.

[KS] D. KOSSMANN, K. STOCKER. Iterative dynamic programming: A new class of query optimization algorithm. ACM Transactions on Database

Systems, 2000.

[SMK] M. STEINBRUNN, G. MARKOETTE, A. KEMPER, Optimizing join order,The VLDB journal, 6(2), 191-208, 1997.

[TSG] A. TSOIS, T. SELLIS, The Generalized Pre-Grouping Transforma- tion: Aggregate Query Optimization in the Presence of Dependencies, in: Proceedings of the 29th VLDB Conference, Berlin, Germany, 2003. [WO] N. PENDSE, What is OLAP,

<http://www.olapreport.com/fasmi.htm>, 3 Marzo 2007

[YLI] W. P. YAN, P. LARSON, Interchanging the order of Grouping and Join, Technical Report CS 95-09, Department of Computer Science, University of Waterloo, Canada, 1995.

[YLEA] W. P. YAN, P. LARSON, Eager Aggregation and Lazy Aggrega- tion, in: Proceedings of the 21st VLDB Conference, Zurich, Swizerland, 1995.

RINGRAZIAMENTI

Per quanto questa pagina sia l’ultima che vado a scrivere per questa tesi `e forse quella che ho desiderato scrivere maggiormente fin dalla mia iscrizione all’universit`a. Desidero ringraziare con particolare attenzione tutti coloro che mi hanno accompagnato in questo cammino e che mi hanno dato sostegno, coscientemente o meno, nel raggiungere questo importante obbiettivo.

Il primo grazie va a mamma, pap`a ed i fratelli per i quali non ci sarebbe bisogno di scrivere nemmeno una parola ma che sono stati di prezioso aiuto nei momenti di difficolt`a e sbandamento che mi sono occorsi in questi anni.

Un ringraziamento speciale a Stefano, il “fratellino” con cui ho condiviso tanto e di cui non vorr`o mai fare a meno nella mia vita. Grazie per avermi mostrato (ancora non l’ho imparato) la calma nelle difficolt`a, il coraggio nel fare le cose, il silenzio nei momenti in cui `e necessario.

Voglio ringraziare Nan`e, Stefano e Riccardo insieme ai quali la mia avven- tura pisana `e iniziata otto anni fa e che oggi sono anche loro ad un passo dal “fatidico obbiettivo”. A voi un grazie ed un in bocca al lupo.

Grazie anche a Fefo, Giovanna, Sacha, Girolamo e Michele, con i quali ho iniziato lo studio dell’informatica e con i quali ho trovato passione in quello che facevo.

Un altro grazie va a Federico, Gaspare e Simone. Senza di loro la lau- rea specialistica non avrebbe avuto il sapore di scoperta e conoscenza che ha invece acquisito nel breve tempo di un mese.

Desidero ancora ringraziare IL PARCHEGGIONE spensierata ed allegra compagnia di persone motivate dalle cose semplici e che nei momenti grigi si `e rivelata in grado di riportare ai miei occhi le cose davvero importanti della vita.

Grazie anche a tutta l’aula studio PACINOTTI, ed ai suoi volontari, nella cui stupenda atmosfera `e nato gran parte di questo lavoro.

Ancora un grazie a tutto il CUS PISA RUGBY, societ`a, allenatori e compa- 73

74 Bibliografia

gni di squadra insieme ai quali ho trascorso un anno stupendo e con i quali mi auguro di trascorrerne ancora tanti.

Ultime che voglio ringraziare, ma sicuramente non per importanza, sono Isa e zia Lisa per quanto in questi anni hanno creduto in me aiutandomi a mantenere la giusta tensione anche quando tutto sembrava difficile. Grazie.

Documenti correlati