Studio di una funzione: (1-3x)/(x-1)
Funzione tratta da http://matepratica.tutorando.com
Funzione tratta da http://matepratica.tutorando.com
Troviamo le chiavi nella relazione
R(A, B, C)
F={A→B, B→C}
A è prima, perché si trova solo a sinistra di una relazione, B e C sono non prime.
Facciamo uno schemino con tre colonne: nella prima ci sono gli attributi che compaiono solo a sinistra, nella terza gli attributi che sono presenti sia a sinistra sia a destra di una DF, in mezzo gli attributi presenti sia a destra sia a sinistra di qualche DF.
S | E | D ---+---+--- A | B | C ---+---+---
Altro esempio:
R(ABCD)
F={AB→C, C→B, C→D}
S | E | D ---+---+--- A | B | D | C | ---+---+---
A+ è dato da A, ma ora dobbiamo trovare la chiusura di AB+, che è ABCD e la chiusura di AC+, che è ACBD.
La chiave primaria è data da ABC.
Altro esempio:
R(ABC)
F={A→B, B→C, C→A}
S | E | D ---+---+--- | A | | B | | C | ---+---+---
"Really sticky situation".
La chiave è (ABC) e la superchiave è - ovviamente - ABC
https://www.youtube.com/watch?v=hTFyG5o8-EA
Una relazione R(A1, A2, ... An)può essere scomposta in due relazioni:
R1(B1, B2, ... Bk)
R2(C1, C2, ... Ck)
e le relazioni risultanti sono di Boyce Codd se:
Per esempio:
Studenti(CodiceFiscale, Nome, Indirizzo, CodiceScuola, NomeScuola, NomeCittà, Punteggio, Priorità)
ha le seguenti DF:
CodiceFiscale → Nome, Indirizzo, Punteggio
Punteggio → Priorità
CodiceScuola → NomeScuola, NomeCittà
è in forma Boyce-Codd?
Le chiavi sono: CodiceFiscale, CodiceScuola.
Ogni DF ha una chiave contenente CodiceFiscale e Scuola? NO! Quindi la relazione non è in BCFN.
Altro esempio:
Iscritto(CodiceFiscale, Nome, Stato, Data, Maggiorenne
La DF è: CodiceFiscale, Nome, Stato → Data, Maggiorenne
è quindi in BCNF.
Input: relazione + dipendenze funzionali
Output: decomposizione di R in relazioni che rispettano la BCNF senza perdita di join
Esempio:
Studenti(CodiceFiscale, Nome, Indirizzo, CodiceScuola, NomeScuola, NomeCittà, Punteggio, Priorità)
ha le seguenti DF:
CodiceFiscale → Nome, Indirizzo, Punteggio
Punteggio → Priorità
CodiceScuola → NomeScuola, NomeCittà
Come sopra, la chiave è CodiceFiscale, CodiceScuola
Creiamo due relazioni
S1(CodiceScuola, NomeScuola, NomeCittà)
S2(CodiceFiscale, Nome, Indirizzo, CodiceScuola, Punteggio, Priorità)
Ora S1 è in BCNF
Invece S2 non è in BCNF, quindi la decomponiamo in:
S3(Punteggio, Priorità)
S4(CodiceFiscale, Nome, Indirizzo, CodiceScuola, Punteggio)
Ora S3 è in BCNF.
Invece S4 non è in BCNF, quindi la decomponiamo in:
S5(CodiceFiscale, Nome, Indirizzo, Punteggio)
S6(CodiceFiscale, CodiceScuola)
Finalmente abbiamo S1, S3, S5, S6 che rappresentano la BCNF della relazione senza perdita di join.
Alcuni esempi, redatti con l'aiuto di http://dblab.dsi.unive.it:8080/
Attributi | Dipendenze funzionali | Chiavi | Attributi primi | Boyce-Codd | 3NF | Commento |
---|---|---|---|---|---|---|
a | - | {(a)} | (a) | R<(a){}> | R<(a){}> | Nessuna d.f. |
a | a→a | {(a)} | (a) | R<(a){}> | R<(a){}> | D.f. banale, non si riporta |
a, b | a→b | {(a)} | (a) | R<(a,b){a→b}> | R<(a,b){a→b}> | |
a, b | a→b, b→a | {(a), (b)} | (a b) | R<(a,b){a→b,b→a}> | R<(a,b){b→a}> | Differenza tra BC e 3NF: nel primo caso sono esplicite entrambe le d.f., nella 3NF solo una |
a, b, c | a→b, b→c | {(a)} | (a) | R1<(a,b){a→b}>, R2<(b,c){b→c}> | R1<(a,b){a→b}>, R2<(b,c){b→c}> | In entrambi i casi, si "estrae" una relazione. Dipendenze preservate. |
Nota bene: b non è una chiave, ma diventa la chiave di una nuova relazione sia secondo BC sia secondo 3NF
a, b, c | a→b, ab→c | {(a)} | (a) | R<(a,b,c){a→b,a→c}> | R<(a,b,c){a→bc}> | b è determinato da a, quindi c è determinato dalla sola a (secondo Boyce-Codd) oppure in ogni caso da ab (secondo 3NF) |
a, b, c | a→b, ab→c, bc→a | {(a),(bc)} | (abc) | R<(a,b,c) {a→b, a→c, bc→a}> | R<(a,b,c) {bc→a}> | |
a, b, c, d, e, g, h, i | adg→gi ach→adg bc→ad ce→ach |
{(bce)} | (bce) | R<(a,b,c) {a→b, a→c, bc→a}> | R<(a,b,c) {bc→a}> |
Funzione tratta da http://matepratica.tutorando.com
Atomicità: un'operazione può essere o completata o annullata, non può essere completata parzialmente
Persistenza: se una transazione termina con successo, le modifiche devono essere mantenute sui dati
Serializzabilità: non possono essere eseguite due transazioni che interferiscono tra loro (ved. esempio due prelievi bancomat contemporanei)
La garanzia per tutti e tre i tipi di problema è il giornale, cioè un log delle transazioni.
Il giornale è compilato con il contenuto delle transazioni e ogni tanto avviene un allineamento con la base dati. L'allineamento può avvenire tramite una sospensione di tutte le transazioni, ma esistono anche tecniche che riducono i tempi di attesa.
Se un'operazione fallisce la transazione si deve DISFARE.
Se un'operazione riesce ma non siamo sicuri che il dato sia scritto nel disco, occorre RIFARE.
Il giornale NON è soggetto a buffering, quindi le informazioni sono sempre scritte direttamente sul disco.
Heap: inserisco i dati a caso. È il metodo utilizzato di default nel filesystem. Può andare bene per pochi dati o accessi sempre su tutti i dati.
Sequenziale: inserisco i dati in ordine, con un ordine scelto a priori. Con un ordinamento sequenziale il costo dell'accesso a un dato è di N*log2(N).
L'ordinamento tipico di ordinamento nei database che memorizzano i dati in modo sequenziale è merge sort. MS si presta bene al calcolo in parallelo su più processori.
L'ordinamento può essere effettuato tramite hash o tramite albero, e può essere statico (le informazioni, una volta inserite, non cambiano) o dinamico.
Nell'hash si trasforma una hash in un indirizzo di pagina. Bisogna gestire le eccezioni (collisioni) e la possibilità che i dati aumentino o diminuiscano molto. L'hash è estremamente efficiente. L'hash si presta molto poco alla ricerca su intervallo.
La struttura ad albero permette sia un accesso diretto a un dato sia a un intervallo con un tempo di esecuzione molto soddisfacente. L'organizzazione ad albero B+ può essere applicato sia al dato sia a un indice.
Inoltre la struttura ad albero restituisce insiemi di dati già ordinati.
Gli indici devono essere usati con parsimonia e buon senso, perché la loro aggiunta selvaggia compromette i tempi delle operazioni di inserimento e la concorrenza nell'accesso ai dati.
La chiave primaria è corredata automaticamente di un indice, perché permette di verificare velocemente se esiste già una chiave uguale o meno.
π e π+ sono le due operazioni algebriche che rappresentano rispettivamente SELECT DISTINCT
e SELECT
.
π+ ha un'esecuzione banale: si eliminano i campi non interessanti e si scrive il risultato.
π invece esclude i duplicati, e funziona:
L'operazione di π si indica con due operazioni (SORT + DISTINCT), a indicare che l'operazione di eliminazione dei duplicati agisce in due fasi diverse.
σ è l'operazione algebrica corrispondente alla clausola WHERE
(HAVING
).
L'operazione funziona in modi diversi se esiste un indice sugli attributi ricercati o se non esiste.
Se non esiste, occorre leggere tutta la tabella e scartare i record non corrispondenti.
Se esiste, il costo è dato dalla somma del costo per l'accesso all'indice e per l'accesso al dato. Il motore decide quale alternativa è migliore; in generale l'indice conviene quando la restrizione è molto selettiva (estrae pochi record).
L'aggregazione senza GROUP BY
legge i record e applica la funzione di aggregazione.
Con GROUP BY bisogna prima raggruppare i dati e successivamente calcolare l'aggregazione.
In particolare, si ordinano i record sull'attributo di ordinamento e poi si calcolano le funzioni di aggregazione.
Anche in questo caso le operazioni sono SORT + GROUP BY.
Gli algoritmi possibili sono:
Lettura dei dati
Proiezione
Restrizione
Ordinamento
Raggruppamento
Giunzione
Due insiemi di DF, F e G, sullo schema R sono equivalenti F ≡ G sse F+ = G+
F è una copertura di G e G è una copertura di F.
o canonica minima, ci permette di definire un insieme di equivalenze in maniera semplice e compatta.
Sia un insieme di dipendenze funzionali F, un attributo è estraneo sse (X-{Ai})→Y∈F+
Per esempio, data una relazione R({Nome, Telefono, Indirizzo, Città, Voto, Materia}, {(Nome, Telefono)→Indirizzo, (Nome, Indirizzo)→Telefono, (Nome, Materia)→Voto, Indirizzo→Città)})
si può scrivere A = Nome, B = Telefono, C = Indirizzo, D = Città, E = Voto, G = Materia
R({A, B, C, D, E, G}, {AB→C, AC→B, AG→E, C→D})
AB→C contiene l'attributo estraneo B, poiché AB-{B}→C è vero, cioè A→C
AC→B contiene l'attributo estraneo C, per lo stesso motivo.
ABGE è una superchiave di R, perché non esistono due elementi con lo stesso valore per gli attributi ABGE.
Però la chiave ABGE contiene un sottoinsieme AG che è superchiave ma è più "ristretta" della superchiave ABGE. Quando una superchiave (come AG) non contiene altre superchiavi più strette, si dice che è chiave.
Gli attributi che non compaiono mai a destra delle DF (come A e G nell'esempio) sono sicuramente contenute in ogni chiave di R.
Gli attributi che compaiono solo a destra delle DF (come D e E nell'esempio) non appartengono a nessuna chiave.
Appartiene a tutte le chiavi | Da determinare | Non appartiene sicuramente ad alcuna chiave |
---|---|---|
A, G | B, C | D, E |
Agli attributi B, C occorre applicare l'algoritmo di chiusura lenta per capire se fanno parte o meno di una chiave.