Basi di dati: riassunto

Indice


Le basi di dati

La capacità di memorizzare e organizzare le informazioni disponibili è un requisito indispensabile per lo svolgimento di molte attività umane. Per base di dati si intende una collezione di dati, utilizzati per rappresentare le informazioni di interesse per lo svolgimento di una qualunque attività.
Più specificamente per database si intende una collezione di dati gestita tramite l’utilizzo di un DBMS (Database management system).
Per DBMS si intende un software in grado di manipolare collezioni di dati garantendo le seguenti proprietà:

  • capacità di gestire grandi moli di dati senza porre limitazioni alla dimensione massima raggiungibile dai dati
  • accesso condiviso ai dati in modo da permettere l’accesso contemporaneo ai dati da parte di più utenti
  • persistenza dei dati in modo che il tempo di vita dei dati non sia legato a quello di esecuzione del programma.

Queste caratteristiche di un DBMS devono essere raggiunte garantendo elevati livelli di affidabilità e di privatezza dei dati memorizzati all'interno della base dei dati. Inoltre il DBMS, come tutti i software, deve svolgere i propri compiti nel modo più efficace (cioè rendendo produttivi i dati memorizzati) ed efficiente (cioè utilizzando al meglio le risorse disponibili) possibile.

L’archiviazione dei dati all'interno di un database avviene definendo dei modelli dei dati tramite delle tecniche di strutturazione. Sebbene esistano diversi modelli di dati, quello maggiormente utilizzato ad oggi è quello di tipo relazionale.
La tecnica con cui il DBMS gestisce i dati internamente definisce il modello logico della base di dati. È anche possibile descrivere i dati in maniera indipendente dal modello logico tramite i modelli concettuali.
Per la definizione delle basi di dati è possibile individuare due tipologie di linguaggi:
    • DDL (Data definition  language) che serve per definire lo schema della base di dati. (Cioè la parte invariante nel tempo della base di dati)
    • DML (Data modification language) che permette di modificare e aggiornare i dati all'interno del database.

Progettazione di basi di dati

Al fine di sviluppare basi di dati in modo completo, efficiente e consistente, negli anni, è stata definita una metodologia di progetto composta dai seguenti passi:
  •  Pianificazione e studio di fattibilità: è un’attività poco standardizzabile in cui il committente espone le proprie necessità al fornitore. In questa fase il fornitore deve cercare di capire quali sono le esigenze del committente e quali sono i dati coinvolti nella progettazione della base di dati e come sono messi in relazione.  Al termine di questa fase viene stabilita in modo generale una stima dei i costi e delle priorità nella realizzazione dei vari componenti del sistema.
  • Raccolta e analisi dei requisiti: in questa fase sono individuati in maniera dettagliata tutti gli aspetti funzionali e tecnologici che la base di dati dovrà soddisfare. Interagendo con il committente si redige un documento in cui sono stabilite e descritte in modo dettagliato tutte le specifiche che il progetto dovrà avere.
  • Progettazione: sulla base delle specifiche raccolte al punto precedente si definisce la struttura dei dati definendone la struttura e l’organizzazione. Questo processo si articola in tre passaggi:
    • Progettazione concettuale
    • Progettazione logica
    • Progettazione fisica
  • Implementazione: sulla base del progetto svolto al punto precedente il database viene implementato attraverso uno dei linguaggi di programmazione disponibili.
  • Validazione/test: questa fase può essere svolta anche in contemporanea con quella di implementazione della base di dati serve e verificare che il prodotto realizzato sia aderente alle specifiche imposte dal progetto e che rispetti determinati standard qualitativi. 
  • Messa in produzione: In questa fase il prodotto viene consegnato al committente e reso disponibile per gli utilizzatori finali. In questa fase possono emergere nuove necessità e problematiche che devono essere risolte tramite l’aggiornamento del prodotto progettato.
Il flusso di progettazione della base di dati può essere rappresentato come una sequenza di passi da percorrere iterativamente. È importante notare però che da ogni punto del percorso è possibile tornare indietro per espandere e migliorare l’intero progetto.

Progettazione concettuale

A partire dai requisiti informativi e dalle specifiche viene creato uno schema concettuale, cioè una descrizione formalizzata dei dati coinvolti dalle specifiche espressa in modo indipendente dal DBMS adottato.
La prima fase della progettazione concettuale prevede l’analisi delle specifiche al fine di realizzare un glossario dei termini in modo da rimuovere sinonimi e omonimi unificando la terminologia utilizzata in tutta la base di dati e al fine di rendere esplicite le relazioni tra i termini utilizzati nella descrizione delle specifiche.
Successivamente, la descrizione delle specifiche raccolte viene ulteriormente analizzata in modo da scomporla in gruppi di frasi omogenee che definiscono gli stessi concetti. I concetti raccolti poi devono essere ulteriormente elaborati in modo da utilizzare le parole definite nel glossario e in modo da suddividerli tra quelli relativi ai dati e quelli relativi alle operazioni su di essi.
Solo a questo punto le specifiche sono raffinata a sufficienza per poter realizzare lo schema ER.
La progettazione dello schema ER può avvenire secondo diverse metodologie di progetto:
  • Top-down: si parte con uno schema molto generale che descrive i concetti generali della base di dati e poi si procede iterativamente raffinandolo e aumentando i dettagli con cui sono descritti i vari concetti.
  • Bottom-up: le specifiche vengono scomposte in blocchi di funzioni elementari. Per ogni blocco di funzioni elementari viene definito uno schema ER e si procede iterativamente ad integrare i vari blocchi fino a comporre lo schema concettuale definitivo.
  • Inside-out: è una metodologia di progetto in cui si modellano prima uno o più concetti fondamentali e poi ci si espande a macchia d’olio verso gli altri concetti che possono essere collegati.
Lo schema concettuale prodotto alla fine di questa fase deve rispettare le seguenti proprietà fondamentali:
  • Correttezza: lo schema rappresenta correttamente (sintatticamente e semanticamente) i requisiti iniziali
  • Completezza: lo schema rappresenta tutti i requisiti
  • Minimalità: lo schema rappresenta solo i requisiti e ogni loro aspetto appare solo una volta
  • Leggibilità: lo schema è facile da interpretare ed esprime i requisiti in modo naturale
  • Modificabilità: lo schema può essere facilmente modificato se i requisiti cambiano
  • Auto-documentabilità: lo schema non ha bisogno di materiale aggiuntivo esterno

Progettazione logica

In questa fase lo schema concettuale viene tradotto in uno schema logico dipendente dal DBMS scelto. È in questo momento che vengono presi in considerazione sia i vincoli di integrità e consistenza che l’efficienza delle operazioni che andranno svolte nella base di dati.
Questa operazione si svolge in due fasi:
  • Ristrutturazione dello schema concettuale: in questa fase lo schema concettuale viene modificato tenendo conto della rappresentazione dei dati all'interno del DBMS e di altri aspetti prettamente legati alla tecnologia utilizzata. Ad esempio è a questo punto che è necessario rimuovere le ridondanze e le generalizzazioni che non possono essere rappresentate dal DBMS.
  • Traduzione nel modello logico: in questa fase vengono definiti gli attributi, le chiavi e i vincoli di integrità referenziale che le tabelle dovranno rispettare.
In questa fase di progettazione è molto importante valutare le prestazioni della base di dati analizzando lo spazio occupato dai dati e il tempo necessario a visitare tutte le entità e relazioni coinvolte nelle operazioni sui dati.
L’analisi delle prestazioni avviene mediante la creazione di alcune tabelle:
  • Tavola dei volumi: per ogni concetto fondamentale viene specificato se esso è una entità o una relazione e una stima del numero di occorrenze.
  • Tavola delle operazioni: per ogni operazione viene stimata la frequenza con cui deve essere svolta e se essa richiede l’interazione con l’utente o se viene eseguita in batch senza che l’utente debba fare nulla.
  • Tavola degli accessi: partendo dalle due tabelle precedenti viene calcolata per ogni operazione il numero di accessi effettuati ad ogni entità e se l’accesso deve avvenire in lettura o scrittura.

Progettazione fisica

In questa fase si operano scelte strettamente dipendenti dallo specifico DBMS scelto definendo lo schema fisico che stabilisce come i dati sono effettivamente memorizzati e le procedure di accesso ai dati (ES indici, clustering ecc..)

Normalizzazione

Lo scopo della normalizzazione è la progettazione di basi di dati che non presentano anomalie.
In particolare tramite la normalizzazione si vogliono evitare le seguenti tipologie di anomalie:
  • Ridondanza dei dati: si vuole evitare che uno stesso dato sia replicato più volte all’interno del DB
  • Anomalie di modifica: si vuole evitare che una modifica di un dato vada ripetuta più volte all’interno della base di dati
  • Anomalie di inserzione: Si vuole evitare che l’inserimento di un nuovo dato debba essere ripetuta più volte in più tabelle all’interno del DB.
  • Anomalie di cancellazione: Si vuole evitare che la cancellazione di un dato debba essere ripetuta più volte su più tabelle all'interno del DB.
È inoltre importante notare che la normalizzazione non costituisce una tecnica di progetto della base di dati ma bensì rappresenta solo un modo per garantire la qualità e l’assenza di anomalie all'interno del database.
Quindi la normalizzazione va applicata solo dopo aver progettato il database analizzando iterativamente lo schema ER e analizzando e risolvendo le anomalie riscontrate.

Nella teoria della normalizzazione sono previste diverse forme normali possibili che definiscono una gerarchia sempre più stringente di specifiche.

La prima forma normale 1NF è la meno stringente e prevede che all'interno di una tabella sia sempre definita una chiave primaria, che i dati definiti all'interno delle colonne appartengano tutti ad uno stesso dominio e soprattutto che i dati rappresentati siano atomici. (ES: tabella che contiene via, città, CAP tutto in un solo campo)
La seconda forma normale 2NF prevede che la relazione sia già in 1NF e che tutti gli attributi di ogni record dipendano interamente dalla chiave primaria. (ES studente(matricola, esame, nome, cognome, voto)  nome e cognome dipendo da matricola mentre voto dipende da esame  devo spezzare in due tabelle)

La terza forma normale 3NF prevede che la relazione sia già in 2NF e che tutti gli attributi siano mutuamente indipendenti, ovvero all'interno di una tabella non devono esserci attributi che dipendono da attributi non chiave. (ES computer(modello, cpu, ram, produttore, sede del produttore)  sede del produttore dipende dall'attributo produttore che non è chiave primaria  devo spezzare in due tabelle)

Infine è possibile definire un’ulteriore forma normale ancora più stringente delle prime tre che è la forma normale di Boyce-Codd. Una relazione è in forma normale Boyce-Codd (BCNF) se è in 1NF e se per ogni dipendenza funzionale non banale X -> Y (con Y diverso da X), X è una superchiave della relazione.
Ad esempio prendendo la relazione studente(Matricola, Codice corso, voto, nome corso, residenza) si possono individuare le seguenti relazioni di dipendenza funzionale:
    • Matricola -> voto, residenza
    • Codice corso -> voto, nome corso
    • Matricola, codice corso -> voto, nome corso, residenza
Da ciò è possibile notare come le prime due dipendenze funzionali non abbiano una superchiave della relazione. Di conseguenza la relazione non rispetta le condizioni per essere in forma BCNF.
Per rendere la relazione in BCNF è necessario suddividere la relazione in due tabelle:
    • Studente(matricola, residenza)
    • Corso(codice corso, nome corso)
    • Esame(Matricola, Codice corso, voto)
La BCNF è una forma normale più stringente rispetto alla 3NF ma a causa di questa rigidità non è sempre possibile portare un database in BCNF. Di conseguenza nella progettazione di una base di dati tipicamente si preferisce raggiungere la 3NF (che è sempre raggiungibile) e solo alla fine si verifica se lo schema ottenuto rispetta anche la BCNF.

SQL

SQL (Structured Query Language) è un linguaggio per basi di dati che offre la possibilità di agire sia a livello di DML permettendo la modifica e l’aggiornamento dei dati presenti che di DDL permettendo di definire lo schema per le nuove entità.

DDL

Tramite il linguaggio DDL, SQL permette di creare nuove entità e di specificarne gli attributi.
Per ogni attributo è possibile definire il dominio che può essere uno di quelli elementari (character, numeric, bit ecc…) o può essere creato ad-hoc da un utente.
L’istruzione fondamentale con cui è possibile creare una nuova entità è CREATE TABLE che ha la seguente sintassi:
CREATE TABLE(NomeAttributo dominio [default] [Vincoli], … )
È a questo livello che è possibile definire i vincoli sugli attributi come ad esempio:

  • Quelli intra-relazionali: not null, unique, primary key
  • Quelli inter-relazionali: references e foreign key
  • Vincoli generici attraverso l’uso di check

È anche possibile specificare il comportamento che le relazioni devono seguire nel momento in cui si verifica una violazione dei vincoli di integrità referenziale specificando le opzioni:

  • Cascade: il nuovo valore viene riportato nella tabella
  • Set null: se il valore cambia nella tabella esterna in quella interna viene settato a null,
  • Set default: come per il caso precedente ma in questo caso viene specificato un valore di default,
  • No action: la modifica di un valore in conflitto con il vincolo di integrità viene proibita.

È inoltre possibile modificare lo schema della base di dati tramite i comandi:

  • Alter table: che permette di aggiungere nuovi attributi
  • Alter domain che permette di modificare il dominio degli attributi già esistenti
  • Drop che permette di eliminare un attributo o un’intera relazione.

DML

Tramite il linguaggio DML, SQL permette l’inserimento, la ricerca e la modifica dei dati presenti nella base di dati.
L’istruzione principale per la ricerca dei dati è SELECT attributi FROM tabella WHERE condizioni.
Tramite questa istruzione vengono ricercati tutti gli attributi specificati che soddisfano la condizione desiderata.
Un’altra istruzione fondamentale del DML offerta da SQL è il JOIN che permette di collegare diverse tabelle. In SQL è possibile realizzare dei JOIN sfruttando le clausole WHERE ma per una migliore leggibilità del codice sono stati definiti dei costrutti dedicati.
SQL mette a disposizione diversi tipi di JOIN:
  • JOIN NATURALE permette di collegare due tabelle prendendo tutti i record che sono presenti sia nella tabella di sinistra che in quella di destra secondo la condizione specificata.
  • LEFT (RIGHT) JOIN permette di collegare due tabelle prendendo tutti i record della tabella di sinistra (o destra)  e collegandoci solo i record corrispondenti della tabella di destra (o sinistra).
  • FULL OUTER JOIN permette di combinare i risultati dei precedenti join prendendo eseguendo prima un join naturale e aggiungendo poi i risultati di un left join e di un right join.
SQL inoltre permette di definire un ordinamento sul risultato di una query mediante l’istruzione ORDER BY.
È possibile anche utilizzare gli operatori insiemistici in SQL:
  • UNION: permette di unire i risultati di due tabelle (unione insiemistica) a condizione che queste abbiano lo stesso schema (cioè che i domini degli attributi siano gli stessi). Come regola generale il risultato di UNION non include i risultati duplicati, se si vogliono includere è necessario specificare UNION ALL
  • EXCEPT: permette di effettuare la differenza insiemistica tra due tabelle selezionando tutti i risultati dalla prima tabella che non compaiono nella seconda
Infine SQL mette a disposizione degli sviluppatori anche i seguenti operatori aggregati:
  • COUNT: conta tutti i risultati
  • SUM: somma i risultati
  • AVG: calcola la media
  • MAX: ricerca il valore massimo
  • MIN: ricerca il valore minimo
Per poter applicare questi operatori a sottoinsiemi del risultato di una query è possibile utilizzare l’operatore GROUP BY. Inoltre se si vuole applicare un operatore aggregato solo ad un sottoinsieme che soddisfi certe condizioni è possibile specificarle all’interno della clausola HAVING. (Nota: HAVING ha un comportamento analogo alla clausola WHERE con la differenza che WHERE si applica alle singole righe mentre HAVING si applica ad un gruppo di righe).

Commenti