I&T Informatica e Telecomunicazioni SpA Progettazione database relazionali Divisione Innovazione Tecnologica Area Data Warehouse I&T Informatica e Telecomunicazioni S.p.A Via dei Castelli Romani, 9 00040 Pomezia (Roma) – Italy Tel. +39-6-911611 Fax +39-6-91601162 http://www.iet.it Relatore: Nino RUSSO [email protected] Maggio 1998 Progettazione database relazionali Indice Prefazione 5 1 Database e DBMS 6 1.1 Cos’è un database 1.2 DataBase Management System (DBMS) 1.3 Caratteristiche di un DBMS 1.3.1 Dati non volatili 1.3.2 Accesso efficiente a grandi quantità di dati 1.3.3 Modello dati 1.3.4 Linguaggi ad alto livello 1.3.5 Gestione delle transazioni 1.3.6 Accesso controllato 1.3.7 Capacità di recupero 1.3.8 Aspetti negativi 6 6 7 8 8 8 8 8 9 9 9 2 Progettazione concettuale 10 2.1 Ciclo di vita dei sistemi informativi 2.2 Modello dei dati e fasi di progettazione 2.2.1 Progetto concettuale del database 2.2.1.1 Livello vista 2.2.1.2 Schemi ed Istanze 2.2.2 Progetto logico del database 2.2.3 Progetto fisico del database 2.2.4 Indipendenza dei dati 2.3 Modello Entità-Relazione 2.3.1 Entità 2.3.2 Set di entità 2.3.3 Attributi e chiavi 2.3.4 Relazioni 2.3.5 Relazioni uno-a-uno 2.3.6 Relazione uno-a-molti 2.3.7 Relazione molti-a-molti 2.3.8 Gerarchia ISA 2.3.9 Attributi delle relazioni 2.4 Esempio di schema concettuale 2.5 Linee guida per tracciare uno schema entità-relazione 2.6 Utilità del diagramma Entità-Relazione 2.7 Altri modelli dati 2.7.1 Modello dati reticolare 2.7.2 Modello dati gerarchico 2.7.3 Modelli orientati agli oggetti 2.7.4 Modelli basati sulla logica 10 11 12 13 13 13 13 14 14 14 14 15 15 15 16 16 17 17 18 21 21 22 22 23 24 26 3 Progettazione logica 29 3.1 Modello dati logico 29 I&T Informatica e Telecomunicazioni SpA 2 Progettazione database relazionali 3.2 Modello dati relazionale 3.3 Rappresentazione dei diagrammi entità-relazione nel modello relazionale 3.3.1 Eliminazione delle gerarchie 3.4 Schema logico del database di esempio 3.5 Vincoli di integrità 3.5.1 Vincoli di chiave 3.5.2 Vincoli di integrità referenziale 3.6 Vantaggi del modello relazionale 3.7 Algebra relazionale 3.7.1 Operatori di base 3.7.1.1 Proiezione 3.7.1.2 Selezione o restrizione 3.7.1.3 Prodotto (cartesiano) o congiunzione 3.7.1.4 Ridenominazione 3.7.1.5 Unione 3.7.1.6 Differenza 3.7.2 Operatori derivati 3.7.2.1 Intersezione 3.7.2.2 Natural join (giunzione naturale) 3.7.2.3 Join (giunzione) 3.7.2.4 Semijoin 3.8 Normalizzazione dei dati 3.8.1 Ridondanza e anomalie 3.8.2 Dipendenze 3.8.2.1 Dipendenze funzionali 3.8.2.2 Dipendenze a molti valori 3.8.2.3 Individuazione delle dipendenze 3.8.3 Scomposizioni 3.8.3.1 Scomposizione lossless join (senza perdita) 3.8.3.2 Scomposizioni che conservano le dipendenze 3.8.4 Prima forma normale 3.8.5 Seconda forma normale 3.8.6 Terza forma normale 3.8.7 Linee guida sulla normalizzazione 3.8.8 Forma normale di Boyce-Codd 3.8.8.1 Osservazioni sulla 3NF e BCNF 3.8.8.2 Analisi non accurata 3.8.9 Quarta forma normale 3.9 Implementazione dello schema logico 29 31 31 34 38 38 38 40 42 42 42 42 42 42 42 42 44 44 44 44 44 46 46 47 47 48 49 49 49 51 53 54 55 57 58 59 59 61 61 4 Progettazione fisica 62 4.1 Strutture fisiche di accesso 4.1.1 Strutture sequenziali 4.1.1.1 Struttura sequenziale entry-sequenced (file sequenziale) 4.1.1.2 Struttura sequenziale ISAM (file indicizzato) 4.1.1.2.1 Ricerca in un indice 4.1.2 Strutture con accesso calcolato (file hashed) 4.1.2.1 Funzioni hash 4.1.3 Strutture ad albero (B-tree) 4.2 Progettazione fisica di una base di dati 62 62 62 62 64 64 65 65 66 Appendice A - Data Flow Diagram I&T Informatica e Telecomunicazioni SpA 69 3 Progettazione database relazionali Appendice B - Evoluzione dei modelli di elaborazione 72 B.1 Mainframe e mini B.2 Modello a personal computer isolati B.3 Modello rete/file server B.4 Modello client/server B.5 Pregi e difetti del modello client/server 72 72 74 76 80 Bibliografia I&T Informatica e Telecomunicazioni SpA 82 4 Progettazione database relazionali Prefazione Nello svolgimento di ogni attività, sia a livello individuale sia in organizzazioni di ogni dimensione, sono essenziali la disponibilità di informazioni e la capacità di gestirle in modo efficace; ogni organizzazione è dotata di un sistema informativo, che organizza e gestisce le informazioni necessarie per perseguire gli scopi dell’organizzazione stessa. Progettare una base di dati significa definire struttura, caratteristiche e contenuto: si tratta, come è facile immaginare, di un processo nel quale bisogna prendere molte decisioni strategiche e l’uso di opportune metodologie è fondamentale per la realizzazione di un prodotto di alta qualità. In questo documento viene illustrato ed esemplificato il processo di progettazione concettuale, logica e fisica dei database relazionali (e una visione generale di altri modelli), che permette, partendo dai requisiti dell’utente, di arrivare a produrre strutture di database di buona qualità. I&T Informatica e Telecomunicazioni SpA 5 Progettazione database relazionali 1 Database e DBMS Chiunque si sia avvicinato al mondo dell’informatica ha sentito parlare di database e DBMS, vediamo che cosa sono. 1.1 Cos’è un database Un database (o base di dati) è un insieme di informazioni permanenti organizzate secondo una struttura definita da un modello dati che rappresenta una situazione reale che si vuole automatizzare (gestione magazzino, fatturazione, personale, ecc.). Nei file tradizionali le informazioni sono organizzate in modo sequenziale, mentre in un database, in accordo con il modello dati, vengono stabilite relazioni tra le varie porzioni di informazioni. Ad esempio, un numero assume significato diverso se è contenuto in file o se è contenuto in un database. Nel primo caso è semplicemente un numero che si trova in una certa posizione del file. Invece in un database ad esso è assegnato un ruolo dal modello dati. Può essere il prezzo di un prodotto che è stato venduto come articolo di un ordine avanzato da un cliente. Ognuno di questi elementi, prezzo, prodotto, articolo, ordine e cliente, è una entità specificata e correlata alle altre dal modello dati. Un database deve soddisfare i seguenti requisiti: • i dati devono essere organizzati con ridondanza minima, ossia non devono essere inutilmente duplicati per evitare spreco di risorse di memorizzazione e, soprattutto, per evitare l’onere della gestione di copie multiple che possono mettere a rischio la consistenza e l’affidabilità dei dati; • i dati devono essere utilizzabili contemporaneamente da più utenti, evitando che ognuno crei una copia propria degli stessi; deve esistere un’unica versione dei dati a cui gli utenti accedono secondo specifici diritti. Inoltre sono necessarie delle tecniche che consentano di evitare che l’attività dei vari utenti generi conflitti per l’uso contemporaneo degli stessi dati. 1.2 DataBase Management System (DBMS) I DBMS sono strumenti software che gestiscono in maniera efficace ed efficiente le informazioni contenute in un database. Prima dello sviluppo dei DBMS l’approccio che veniva applicato al problema dell’archiviazione prevedeva l’uso diretto delle strutture del file system (vedi fig. 1.1). Appl. 1 Appl. 2 Appl. 3 Fig. 1.1 Approccio file system I&T Informatica e Telecomunicazioni SpA 6 Progettazione database relazionali Nella soluzione file system, le applicazioni accedono direttamente agli archivi, quindi ognuna deve conoscere la struttura interna degli archivi e le relazioni tra i dati e deve evitare la duplicazione degli stessi. Inoltre la non volatilità dei dati e la gestione degli accessi contemporanei di più applicazioni agli archivi viene relegata a strati software non specializzati per tali compiti, quali il sistema operativo. La caratteristica saliente che differenzia un sistema per la gestione di database (DB) è la presenza di un componente specializzato a tale ruolo (vedi fig. 1.2). Appl. 1 D B Appl. 2 M DB S Appl. 3 Fig. 1.2 Approccio DBMS La figura 1.2 mostra come le applicazioni rivolgono al DBMS le proprie richieste di accesso alla base di dati, il quale gestisce i dati svincolando le applicazioni da tale onere. Quindi il DBMS è un modulo, specializzato nella gestione del DB; a cui tutte le applicazioni si rivolgono per accedere ai dati. Si ottiene così un triplice scopo: da una parte le funzionalità di gestione del database sono raggruppate in un unico insieme, dall’altra le applicazioni risultano alleggerite e quindi più veloci da realizzare e, soprattutto, nessuna potrà effettuare operazioni scorrette sul database. 1.3 Caratteristiche di un DBMS Le proprietà fondamentali di un DBMS sono: • Capacità di gestire dati non volatili; • Capacità di accedere in modo efficiente a grandi quantità di dati. Sono richieste, inoltre, le seguenti caratteristiche: • Mantenimento di un modello dati, o astrazione matematica tramite la quale l’utente può osservare i dati; • Mantenimento di linguaggi di alto livello che permettono all’utente di definire la struttura dei dati, accedere ad essi ed elaborarli; • Gestione delle transazioni, cioè capacità di fornire un accesso corretto e concorrente al DB da parte di molti utenti contemporaneamente; • Accesso controllato, cioè capacità di limitare l’accesso ai dati agli utenti non autorizzati e di controllare la validità dei dati; • Capacità di recupero, cioè la possibilità di ripristino a seguito di guasti del sistema senza perdere dati. I&T Informatica e Telecomunicazioni SpA 7 Progettazione database relazionali 1.3.1 Dati non volatili Un DBMS deve trattare dati non volatili, nello specifico deve trattare un database che contiene i dati che si vogliono gestire e le informazioni che servono per gestirli. Ovviamente i dati per essere non volatili devono essere memorizzati su memorie di massa. 1.3.2 Accesso efficiente a grandi quantità di dati Un DBMS deve permettere, a differenza di un file system, di accedere in maniera rapida a porzioni arbitrarie di dati contenuti nel DB. Questa capacità diventa necessaria soprattutto quando la mole dei dati è molto grande, mentre per quantità piccole di solito bastano anche tecniche di accesso semplice, come quella della scansione lineare. 1.3.3 Modello dati Ogni DBMS fornisce almeno un modello astratto di dati, che consente all’utente di considerare le informazioni non come sequenza di bit, ma in termini a lui più comprensibili. Per operare sulle informazioni contenute in un database è possibile, quindi, ignorare i dettagli della struttura fisica del DB e considerare i dati in termini di ciò che rappresentano nel mondo reale o, comunque, in relazione al livello di astrazione del modello dei dati del database. 1.3.4 Linguaggi ad alto livello Un DBMS supporta tradizionalmente tre tipi di linguaggi, distinti in base alle funzioni eseguite sui dati. Tale distinzione è dovuta alla separazione delle funzioni dichiarative da quelle di elaborazione e di controllo, a differenza di quanto avviene in un comune linguaggio di programmazione. Il motivo è che, mentre in un normale programma i dati esistono solo mentre esso è in esecuzione, in un DB i dati sono permanenti e possono essere dichiarati una volta per tutte. Per la definizione dello schema logico del database viene usato il DDL (Data Definition Language). Esso non è un linguaggio procedurale, piuttosto è una notazione per definire le informazioni e le relazioni intercorrenti fra esse, secondo un particolare modello dati. Per le operazione di interrogazione ed aggiornamento dei dati quali inserimento, modifica, cancellazione, e così via, viene usato il DML (Data Manipulation Language). Esso può essere disponibile come linguaggio a se stante o come un insieme di istruzioni richiamabili da un linguaggio di programmazione che svolge il ruolo di linguaggio host. Per le operazioni di controllo dei dati, la gestione degli utenti, l’assegnazione dei diritti di accesso, l’ottimizzazione del funzionamento del DBMS viene usato il DCL (Data Control Language). Solitamente il DML è utilizzato dai programmatori che realizzano i programmi applicativi destinati agli utenti finali, mentre il DCL e il DDL sono usati dal DBA (Data Base Administrator), la persona o il gruppo di persone che partecipa alla progettazione e al mantenimento del database. Un’altra figura che partecipa alla progettazione del DB è il DA (Data Administrator), figura di più alto livello rispetto al DBA, che si occupa dei dati come patrimonio del sistema informativo aziendale, indipendentemente dalla loro localizzazione all’interno di un DB. 1.3.5 Gestione delle transazioni Un’altra caratteristica importante di un DBMS è la sua capacità di gestire simultaneamente grandi quantità di transazioni, cioè di procedure operanti sul DB. Alcuni DB sono così grandi che possono essere utili solo se su di essi operano simultaneamente diverse applicazioni. I sistemi usati dalle banche, a cui accedono quasi istantaneamente centinaia o migliaia di macchine per interrogazioni e almeno altrettanti impiegati delle filiali, costituiscono un tipico esempio di questi DB. A volte due accessi non interferiscono tra loro; ad esempio il saldo di un conto bancario può essere letto nello stesso tempo, senza problemi di inconsistenza, da qualunque numero di transazioni. Altre volte, come nel caso di un prelievo che avviene contemporaneamente ad un versamento, il risultato di due transazioni simultanee e senza coordinazione può essere imprevedibile. I&T Informatica e Telecomunicazioni SpA 8 Progettazione database relazionali Quindi, le transazioni che modificano un campo, devono bloccare altre transazioni che cercano di leggere o scrivere lo stesso campo nel medesimo istante. Perciò un DBMS deve fornire controlli di concorrenza per evitare che più di una transazione acceda allo stesso dato in modo non coordinato. 1.3.6 Accesso controllato Le funzionalità di un DBMS di gestione degli utenti consente all’amministratore del sistema di definire dei vincoli di accesso ai dati, ovvero di stabilire per ciascun utente i diritti di accesso (lettura, modifica e così via) alle singole unità di informazione del database. Inoltre un DBMS fornisce spesso una funzione di view (vista) che consente di creare oggetti astratti a partire da oggetti reali permettendo visione logiche diverse dello stesso insieme di dati; ciò comporta la possibilità di rendere disponibile a determinate categorie di utenza l’intero database, ad altri solo una parte. 1.3.7 Capacità di recupero Un DBMS, oltre a trattare dati non volatili, deve implementare delle tecniche che permettano il ripristino dei dati persi o danneggiati a seguito di un malfunzionamento di una qualsiasi componente del sistema. La maggior parte dei DBMS esistenti gestisce un file detto log delle transazioni nel quale si tiene traccia di tutti i cambiamenti che avvengono nel database. Ogni volta che un utente avvia una transazione che modifica il DB, il DBMS registra la modifica nel log delle transazioni. Quando la transazione è conclusa nel log viene segnalato che le modifiche della transazione sono definitive. Se, ad esempio, si verifica un crash del sistema dovuto ad una caduta di tensione, ci saranno dei dati modificati che non sono stati ancora scritti nel database, ma grazie al log delle transazioni, si potrà ricostruire la transazione persa. Per il recovery di problemi più seri come il crash del disco rigido non sono più sufficienti i log delle transazioni ma è necessario avere un backup (copia su dispositivi di memorizzazione esterni) del DB o di una parte di esso. Il DBMS deve fornire gli strumenti adatti ad assolvere a questo compito. 1.3.8 Aspetti negativi I DBMS hanno anche degli aspetti negativi: • I DBMS sono prodotti costosi, complessi e abbastanza diversi da molti altri strumenti informatici. La loro introduzione comporta quindi notevoli investimenti, diretti (acquisto del prodotto) e indiretti (acquisizione delle risorse hardware e software necessarie, conversione delle applicazioni, formazione del personale). • I DBMS forniscono, in forma integrata, una serie di servizi, che sono necessariamente associati ad un costo. Nei casi in cui questi servizi non sono tutti necessari, è difficile scorporare i servizi effettivamente richiesti dagli altri, e ciò può comportare una riduzione di prestazioni. I&T Informatica e Telecomunicazioni SpA 9 Progettazione database relazionali 2 Progettazione concettuale La progettazione concettuale è la prima fase che viene eseguita nella costruzione di una base di dati, e in essa si produce, uno schema concettuale che rappresenta la realtà di interesse. Nel seguente capitolo illustreremo questo processo e i modelli dati che permettono di realizzare lo schema concettuale suddetto, in particolare, il modello entità-relazione che è al momento il più diffuso. Prima di ciò, però, vediamo la metodologia di progettazione. 2.1 Ciclo di vita dei sistemi informativi La progettazione di una base dati costituisce solo una componente del processo di sviluppo, all’interno di una organizzazione, di un sistema informativo complesso e va quindi inquadrata in un contesto più ampio, quello del ciclo di vita dei sistemi informativi. Come illustrato in figura 2.1, il ciclo di vita di un sistema informativo comprende, generalmente, le seguenti attività. Studio di fattibilità Raccolta e analisi dei requisiti Progettazione Implementazione Validazione e collaudo Funzionamento Fig. 2.1 Ciclo di vita di un sistema informativo • Studio di fattibilità. Serve a definire, in maniera per quanto possibile precisa, i costi delle varie alternative possibili e a stabilire le priorità di realizzazione delle varie componenti del sistema. • Raccolta e analisi dei requisiti. Consiste nella individuazione e nello studio delle proprietà e delle funzionalità che il sistema informativo dovrà avere. Questa fase richiede una interazione con gli utenti del sistema e produce una descrizione completa, ma generalmente informale, dei I&T Informatica e Telecomunicazioni SpA 10 Progettazione database relazionali • • • • dati coinvolti (anche in termini di previsione sulla loro frequenza). Vengono inoltre stabiliti i requisiti software e hardware del sistema informativo. Progettazione. Si divide generalmente in progettazione dei dati e progettazione delle applicazioni. Nella prima si individua la struttura e l’organizzazione che i dati dovranno avere, nell’altra si definiscono le caratteristiche dei programmi applicativi. Le due attività sono complementari e possono procedere in parallelo o in cascata. Le descrizioni dei dati e dei programmi prodotte in questa fase sono formali e fanno riferimento a specifici modelli. Implementazione. Consiste nella realizzazione del sistema informativo secondo la struttura e le caratteristiche definite nella fase di progettazione. Viene costruita e popolata la base di dati e viene sviluppato il codice dei programmi. Validazione e collaudo. Serve a verificare il corretto funzionamento e la qualità del sistema informativo. La sperimentazione deve prevedere, per quanto possibile, tutte le condizioni operative. Funzionamento. In questa fase il sistema informativo diventa operativo e richiede, a meno di malfunzionamenti o revisioni delle funzionalità del sistema, solo operazioni di gestione e manutenzione. Va detto che accanto alle attività citate, viene oggi spesso effettuata anche una attività detta di prototipizzazione, che consiste nell’uso di specifici strumenti software per la realizzazione rapida di una versione semplificata del sistema informativo, con la quale sperimentare le sue funzionalità. La verifica del prototipo può portare a una modifica dei requisiti e una eventuale revisione del progetto. Poiché i dati hanno un ruolo centrale nei sistemi informativi si giustifica uno studio autonomo relativo alla progettazione delle basi di dati che si individua nella terza fase del ciclo di vita riportato in figura 2.1. 2.2 Modello dei dati e fasi di progettazione Nel corso degli anni, nell’ambito delle basi di dati, si è consolidata una metodologia di progetto articolate in tre fasi principali da effettuare in cascata. Essa si fonda su un principio molto semplice ma efficace: quello di separare in maniera netta le decisioni relative a “cosa” rappresentare in una base dati (prima fase), da quelle relative a “come” farlo (fasi successive). Ogni fase si riferisce a un livello di astrazione nella rappresentazione dei dati e delle relazioni tra essi, e ha lo scopo di separare le attività di risoluzione dei problemi e di garantire la possibilità di modificare delle soluzioni adottate ai livelli inferiori senza dover riprogettare quanto definito nei livelli superiori. A ciascuna fase di progettazione corrispondono diversi modelli per la rappresentazione dei dati, ovvero tecniche per la rappresentazione degli aspetti rilevanti della realtà da modellare, definite da strumenti e vincoli specifici. La rappresentazione generata seguendo le regole del modello viene definita schema (vedi fig. 2.2). realtà di interesse modello (regole di rappresentazione) schema Fig. 2.2 Realtà/modello/schema I&T Informatica e Telecomunicazioni SpA 11 Progettazione database relazionali Le fasi riconosciute fondamentali nella progettazione di un database sono le seguenti: progetto concettuale, progetto logico e progetto fisico (vedi figura 2.3). Requisiti della base di dati Progettazione di base di dati Progetto concettuale Modello concettuale Schema concettuale Progetto logico Modello logico Schema logico Progetto fisico Modello fisico Schema fisico Prodotti della progettazione Fig. 2.3 Fasi della progettazione di una base di dati 2.2.1 Progetto concettuale del database Obiettivo della fase di progettazione concettuale è la rappresentazione completa (formale) della realtà di interesse (informale) ai fini informativi, in maniera indipendente da qualsiasi specifico DBMS e quindi senza tenere conto degli aspetti implementativi. Tale rappresentazione, detta schema concettuale (che fa riferimento a un modello concettuale dei dati), è la rappresentazione più astratta, ovvero più vicina alla logica umana, nella definizione di dati e relazioni. I modelli dei dati usati nella progettazione concettuale vengono definiti modelli semantici. Nel corso degli anni sono stati definiti diversi modelli dei dati ad iniziare da quelli reticolari e gerarchici seguiti da quello entità-relazione e infine quelli orientati agli oggetti e alla logica. I&T Informatica e Telecomunicazioni SpA 12 Progettazione database relazionali 2.2.1.1 Livello vista Una vista, sottoschema, o subschema, è una parte del database concettuale o un’astrazione di parte del database concettuale. In un certo senso, la costruzione delle viste è l’inverso del processo di integrazione di un database: per ogni collezione dei dati che hanno contribuito alla costruzione del database concettuale globale, possiamo costruire una vista che contenga proprio quei dati. Le viste sono importanti anche per far valere la sicurezza in un sistema di database, permettendo solo agli utenti che ne hanno l’autorizzazione di osservare i sottoinsiemi dei dati. Spesso una vista è proprio come un piccolo database concettuale ed ha lo stesso livello di astrazione. Però, in un certo senso, una vista può essere “più astratta” di un data base concettuale, in quanto i dati in essa coinvolti possono essere costruiti a partire dal database concettuale, senza però essere effettivamente presenti in quel database. 2.2.1.2 Schemi ed Istanze Quando si progetta un database si è interessati al suo schema, quando invece si usa si è interessati ai dati effettivamente presenti in esso. Si noti che i dati nel database cambiano frequentemente, mentre gli schemi rimangono gli stessi per lungo tempo. Il contenuto corrente del database si chiama istanza del database (o estensione del database o stato del database). Come visto, il termine schema è usato nelle varie fasi della progettazione di un database, così avremo schema concettuale per riferirsi al livello di progettazione concettuale del database, schema logico per il progetto logico, schema fisico per il progetto fisico e semplicemente sottoschema per il livello delle viste. 2.2.2 Progetto logico del database La fase di progettazione logica del database ha lo scopo di tradurre lo schema concettuale espresso mediante un modello semantico in una rappresentazione mediate un modello logico dei dati. La rappresentazione che si ottiene viene definita schema logico del database. A differenza dello schema concettuale, lo schema logico dipende strettamente dal tipo di DBMS utilizzato e in particolare del suo modello logico dei dati. Un modello logico dei dati è quindi la tecnica di organizzazione e di accesso ai dati utilizzata da specifiche categorie di DBMS. In particolare, in riferimento al modello logico dei dati su cui si basano, vengono distinti DBMS gerarchici, reticolari, relazionali, ad oggetti e basati sulla logica. Un ulteriore compito della progettazione logica è quello di dichiarare le viste, tramite il DDL o gli specifici linguaggi di definizione dei dati del sottoschema. Successivamente per presentare interrogazioni ed operazioni su tali viste, può essere previsto un linguaggio di manipolazione del sottoschema altrimenti viene usato il DML generico. 2.2.3 Progetto fisico del database Nel progetto fisico viene stabilito come le strutture a livello logico debbano essere organizzate negli archivi e nelle strutture del file system: esso dipende quindi non solo dal tipo di DBMS utilizzato, ma anche dal sistema operativo e in ultima istanza dalla piattaforma hardware del sistema che ospita il DBMS. E’ pertanto il livello di progettazione in cui si può far uso del minor livello di astrazione, dovendo rispettare i vincoli tecnici imposti dal sistema ospite. I&T Informatica e Telecomunicazioni SpA 13 Progettazione database relazionali 2.2.4 Indipendenza dei dati La catena di astrazione della figura 2.3, dal database concettuale, a quello logico e a quello fisico, fornisce due livelli di “indipendenza dei dati”. E’ ovvio che in un database ben progettato, lo schema fisico possa essere modificato senza alterare quello logico e senza richiedere una ridefinizione dei sottoschemi. Questa indipendenza è nota come indipendenza fisica dei dati. Ciò implica che le modifiche all’organizzazione del database fisico possono alterare l’efficienza dei programmi applicativi, ma non sarà mai chiesto di riscrivere tali programmi solo perché lo schema fisico ha modificato l’implementazione dello schema logico. Anche la relazione tra vista e il database concettuale, fornisce un tipo di indipendenza chiamata indipendenza logica dei dati. L’uso del database può rendere necessario modificare lo schema concettuale, per esempio aggiungendo informazioni su diversi tipi di entità o altre informazioni su entità già esistenti. Lo schema concettuale può subire molte modifiche, senza coinvolgere i sottoschemi esistenti, mentre altri tipi di variazione allo schema concettuale possono essere fatte solo ridefinendo la corrispondenza tra sottoschema e schema concettuale. Ancora una volta non sono necessari variazioni ai programmi applicativi. L’unico tipo di variazione dello schema concettuale che non si riflette in una semplice ridefinizione della corrispondenza col sottoschema, si verifica quando vengono cancellate alcune informazioni del sottoschema. Naturalmente tali variazioni richiederanno la riscrittura o l’eliminazione di alcuni programmi applicativi. 2.3 Modello Entità-Relazione Lo scopo del modello Entity-Relationship (Entità-Relazione E-R) è quello di permettere la descrizione dello schema concettuale di una situazione reale senza preoccuparsi dell’efficienza o della progettazione del database fisico, che ci si aspetta invece nella maggior parte dei modelli fisici. Di solito si pensa che lo schema entità-relazione così costruito sia poi tradotto in uno schema logico di un modello logico dei dati, ad esempio quello relazionale, che al momento è il più diffuso. 2.3.1 Entità Il modello entità-relazione, prevede come prima attività della progettazione concettuale, la individuazione delle entità. Una entità è qualcosa che esiste ed è distinguibile: possiamo cioè riconoscere un’entità tra le altre. Ad esempio ogni persona è un’entità, così come ogni automobile. 2.3.2 Set di entità Un gruppo composto da entità tutte “simili” forma un set di entità. Esempi di set di possono essere: 1) tutte le persone 2) tutte le persone coi capelli rossi 3) tutte le automobili Negli esempi 1) e 2), osserviamo persone e persone coi capelli rossi: il termine “entità simili” non è definito in modo preciso e si possono stabilire infinite proprietà diverse con cui definire set di entità. Nella progettazione del modello concettuale di un database, la scelta dei set di entità, è una operazione fondamentale così come è importante individuare tutte le proprietà caratteristiche di un set di entità che vengono descritte mediante gli attributi. Dalla “somiglianza”, quindi, nasce la necessità dell’individuazione di un insieme di caratteristiche comuni a tutti gli elementi del set di entità. Il set di entità è un concetto a livello di schema, mentre il corrispondente concetto a livello di istanza è il relativo sottoinsieme corrente di tutti gli elementi del dato set di entità nel database. I&T Informatica e Telecomunicazioni SpA 14 Progettazione database relazionali Ad esempio il Pubblico Registro Automobilistico può progettare il suo schema di database avente il set di entità Automobili. L’istanza corrente di questo set di entità riguarderà tutte le automobili immatricolate sino ad ora in Italia, ma non tutte le automobili del mondo o tutte le automobili mai esistite. Lo schema entità-relazione ha una rappresentazione grafica che permette di avere immediatamente la visione globale dello schema concettuale del database. La rappresentazione grafica che si ottiene, a volte, invece di schema, viene chiamata diagramma entità-relazione (Entity-Relationship Diagram – ERD). In questa rappresentazione grafica si usa una convenzione per rappresentare i vari oggetti. I set di entità vengono rappresentate con dei rettangoli con il nome del set di entità all’interno. 2.3.3 Attributi e chiavi Come già detto, i set di entità possiedono delle proprietà, chiamate attributi, le quali associano ad ogni entità del set un valore appartenente al dominio dei possibili valori per quell’attributo. Di solito il dominio sarà un insieme di interi, numeri reali, stringhe di caratteri, valori booleani ma anche immagini, audio e video come nei più recenti database multimediali. La scelta degli attributi caratteristici per i set di entità è un punto abbastanza critico nell’ideare lo schema concettuale di un database. Tra tutti gli attributi di un particolare set di entità ne va scelto uno o un insieme, i cui valori identificano in modo univoco ogni entità del set. Questo attributo o insieme di attributi è chiamato chiave per quel dato set. In linea di principio ogni set di entità possiede una chiave soddisfacendo la richiesta che ogni entità sia distinguibile da ogni altra. Ma se per un set di entità scegliamo un insieme di attributi tra i quali non si possa individuare una chiave, non saremo in grado di distinguere una entità dall’altra. Però è possibile fornire un codice identificativo arbitrario da usare come chiave. La rappresentazione grafica degli attributi è un’ellisse con il nome dell’attributo scritto all’interno e si collega con il rispettivo set di entità con dei segmenti (non orientati). Agli attributi che fanno parte della chiave per il rispettivo set, viene aggiunta una sottolineatura al nome. Nel caso speciale di set di entità con un singolo attributo, a volte si identifica il set con l’attributo stesso, chiamando il set col il nome dell’attributo. In tal caso, invece che con un rettangolo, il set di entità è rappresentato con un’ellisse collegata a qualunque relazione con cui sia coinvolto il set di entità. 2.3.4 Relazioni Le dipendenze o associazioni di interesse informativo tra i dati da rappresentare vengono espresse nel modello entity-relationship mediante relazioni tra le corrispondenti entità. Le relazioni dello stesso tipo compongono l’insieme di relazioni (relation set) tra i due insiemi di entità. Per ottenere un modello adeguato del mondo reale, spesso è necessario classificare le relazioni a seconda del numero di entità associabili tra un set di entità e l’altro. 2.3.5 Relazioni uno-a-uno La relazione più semplice, e più rara, fra le relazioni che collegano due set è quella uno-a-uno, cioè che ogni entità di un set è legata con al più un elemento dell’altro set. Le relazioni vengono rappresentate graficamente con dei rombi e vengono collegati ai propri set di entità con dei segmenti orientati o non a seconda del tipo di relazione. Nel caso di relazione uno-auno il segmento è orientato in entrambi i versi. Un’alternativa all’utilizzo dei segmenti orientati è quella di mettere sui segmenti che collegano la relazione ai set dei numeri che indicano la cardinalità della relazione. Un esempio di relazione 1:1 è la relazione tra nazioni e capitali. Ogni nazione ha un’unica capitale, ad una capitale corrisponde un’unica nazione (fig. 2.4). I&T Informatica e Telecomunicazioni SpA 15 Progettazione database relazionali Nome Cap. Nome Naz. Estensione Nazioni Capitale Capitali Abitanti Popolazione Fig. 2.4 Diagramma E-R della relazione1:1 tra nazioni e capitali. Nazioni ha tre attributi: Nome Naz. (chiave), Estensione e Popolazione. Capitali ha due attributi: Nome Cap. (chiave), Abitanti. 2.3.6 Relazione uno-a-molti Due set E1 ed E2 sono in relazione uno-a-molti da E1 ad E2 se una entità nel set E1 è associata con zero o più entità nel set E2, ma ogni entità in E2 è associata con al più una entità in E1. Un esempio di relazione 1:N è la relazione tra madri e figli. Una madre può avere più figli, mentre ad un figlio corrisponde un’unica madre (fig. 2.5). La rappresentazione grafica della relazione 1:N è un rombo con segmenti che uniscono i set di entità coinvolti e orientati soltanto nella direzione del set di entità con cardinalità uno. Madri Figlio Figli Fig. 2.5 Relazione 1:N tra il set Madri e il set Figli. Da notare il verso della freccia (nella figura non sono stati indicati gli attributi dei set di entità) 2.3.7 Relazione molti-a-molti Due set E1 ed E2 sono in relazione molti-a-molti se ad ogni elemento di E1 possono corrispondere più elementi di E2 e viceversa. Sulle relazioni molti-a-molti è da notare il fatto che non esistono efficienti strutture dati per la loro implementazione, spesso è richiesto di scomporre tali relazioni con varie relazioni molti-a-uno. Un esempio di relazione N:M è la relazione tra corsi e studenti. Un corso è seguito da più studenti, e lo stesso studente segue più corsi. Un altro esempio di relazione N:M è quella tra libri e autori. Un libro può essere scritto da più autori, un autore può aver scritto più libri (fig. 2.6). La rappresentazione grafica della relazione N:M è un rombo con segmenti non orientati che uniscono i set di entità coinvolti. I&T Informatica e Telecomunicazioni SpA 16 Progettazione database relazionali Autori Libri Scritto Fig. 2.6 Relazione N:M tra il set Autori e il set Libri 2.3.8 Gerarchia ISA Un tipo particolare di relazione è quella chiamata ISA o sottotipo/supertipo. Diciamo che A isa B, cioè “A è un B” (A è il sottotipo e B è il supertipo), se il set di entità B è una generalizzazione di entità del set A, o in modo equivalente se A è un tipo particolare di B. Lo scopo principale per dichiarare le relazioni isa tra i set di entità A e B è che in tal modo A eredita gli attributi di B, ma avrà anche attributi che non avrebbero necessariamente significato per gli elementi di B che non siano anche elementi di A. La rappresentazione grafica della gerarchia isa è un rombo con etichetta isa con segmenti orientati nella direzione del set supertipo. Un esempio di relazione isa è quello di una società che può avere un set di entità Dipendenti con attributi Matricola, Nome e Stipendio. Se la società fosse una squadra di calcio, alcuni dei dipendenti, i Giocatori, avrebbero altri importanti attributi come Ruolo (portiere, difensore, attaccante), che non riguarderebbero gli altri dipendenti. Il modo migliore per progettare questo schema, è quello di avere un altro set di entità, Giocatori, legato con la relazione isa al set Dipendenti. Gli attributi (anche le chiavi) che appartengono a Dipendenti (Matricola, Nome, Stipendio), verrebbero ereditati da Giocatori, ma solo Giocatori avrebbe un attributo come Ruolo (fig. 2.7). Matricola Nome Isa Dipendenti Giocatori Ruolo Stipendio Fig. 2.7 Gerarchia Giocatori isa Dipendenti. Giocatori e’ il sottotipo (A della definizione) e Dipendenti è il supertipo (B della definizione). 2.3.9 Attributi delle relazioni Il modello entità-relazione prevede che anche gli insiemi delle relazioni abbiano degli attributi che ne specificano le caratteristiche. Tali attributi vengono rappresentati graficamente con una ellisse, cioè come per gli attributi di un set di entità, con un segmento orientato nel verso che va dal rombo all’ellisse (fig. 2.8). Nome Attributo Relazione E1 R1 E2 Fig. 2.8 Rappresentazione attributi relazione I&T Informatica e Telecomunicazioni SpA 17 Progettazione database relazionali 2.4 Esempio di schema concettuale Adesso viene proposto un esempio di schema concettuale che sarà usato anche nel successivo capitolo per vedere come uno schema concettuale si traduce in uno schema logico. L’esempio che si introduce è quello del database Mobili Componibili, che fa parte del sistema informativo di un mobilificio e che rappresenta la seguente situazione: • gli articoli, di cui interessa archiviare la descrizione, il prezzo, l’aliquota IVA e le spese di trasporto, sono suddivisi in categorie: • ciascun articolo è costituito da una serie di componenti, di cui vengono archiviati la descrizione e il costo; • i componenti vengono prodotti da singoli laboratori; di ogni laboratorio viene memorizzato l’indirizzo, la città e il telefono; • gli articoli possono comparire negli ordini; di ogni ordine viene archiviata la data; • infine gli ordini sono effettuati dai negozi di cui viene archiviato il nome, l’indirizzo, la città, e il telefono. Nel progetto concettuale vengono individuate i seguenti set di entità con rispettivi attributi e chiavi. Set di Entità Attributi Chiave Categoria Cat_Cod Cat_Descrizione X Articolo Art_Cod Art_Descrizione Art_Prezzo Art_IVA Art_Spese_Trasporto X Componente Com_Cod Com_Descrizione Com_Costo X Laboratorio Lab_Cod Lab_Indirizzo Lab_Città Lab_Telefono X Negozio Neg_Cod Neg_Nome Neg_Indirizzo Neg_Città Neg_Telefono X Ordine Ord_Cod Ord_Data X Fig. 2.9 Set di entità, attributi e chiavi dello schema concettuale di esempio I&T Informatica e Telecomunicazioni SpA 18 Progettazione database relazionali Tra tali set di entità sussistono le seguenti relazioni: • Categoria e Articolo hanno una relazione di tipo 1:N, in quanto ciascuna categoria può contenere più articoli, mentre un articolo può appartenere ad una solo categoria. Chiamiamo questa relazione Appartiene; • Articolo e Componente sono in relazione N:M, in quanto ciascun articolo è composto da più componenti e ciascun tipo di componente può entrare nella composizione di pù articoli; può poi essere necessario utilizzare più pezzi di un certo componente per comporre un determinato articolo, per cui un attributo della relazione è la quantità. Chiamiamo questa relazione Composto; • Laboratorio e Componente sono in relazione 1:N in quanto un laboratorio può costruire più componenti, mentre un determinato componente viene prodotto da un solo laboratorio. Chiamiamo questa relazione Prodotta; • Negozio e Ordine sono in relazione 1:N, in quanto un negozio può effettuare più ordini, mentre ciascun ordine è relativo a un unico negozio. Chiamiamo questa relazione Effettuato; • Ordine e Articolo sono in relazione N:M, in quanto in un ordine possono essere richiesti più articoli e un articolo può comparire in più ordini; la relazione ha come attributo la quantità nella quale un certo articolo viene richiesto nell’ordine. Chiamiamo questa relazione Richiesto. La figura 2.10 mostra la rappresentazione dello schema concettuale del database Mobili Componibili mediante il modello entità-relazione. I&T Informatica e Telecomunicazioni SpA 19 Progettazione database relazionali Neg_Nome Neg_Cod Ord_Cod Neg_Indirizzo Negozio Effettuato Ordine Ord_Data Neg_Città Neg_Telefono OrdArt_Qta Richiesto Art_Cod Art_Descriz. Cat_Cod Categoria Appartiene Articolo Art_Prezzo Cat_Descriz. Art_IVA Art_Spese_Trasp ComArt_Qta Composto Lab_Cod Com_Cod Lab_Indiriz. Laboratorio Prodotta Componente Com_Desciz. Lab_Città Com_Costo Lab_Telefono Fig. 2.10 Schema Concettuale del DB Mobili Componibili secondo il modello entità-relazione. (Schema o Diagramma Entità-Relazione ERD) I&T Informatica e Telecomunicazioni SpA 20 Progettazione database relazionali 2.5 Linee guida per tracciare uno schema entità-relazione 1) Perfetta comprensione della realtà che si vuole rappresentare. 2) Individuazione dei set di entità. • Studiare la descrizione del Contesto a cui ci si riferisce e la definizione degli Obiettivi del Progetto. • Individuare i Nomi degli Obiettivi/Concetti che è indispensabile citare per descrivere Contesto e Obiettivi. • Valutare se si tratta di Nomi di Entità che dovranno essere gestite (o referenziate) dal sistema in esame. 3) Individuazione degli attributi che caratterizzano i set di entità trovati al passo precedente, e scelta (o definizione) della chiave per ogni set di entità. 4) Individuazione delle relazioni tra i vari set di entità e definizione della loro cardinalità. • Studiare la descrizione del Contesto a cui ci si riferisce e la definizione degli Obiettivi del Progetto. • Individuare le frasi che legano fra loro due set di entità con un verbo (Entità soggetto + verbo + Entità oggetto). • Valutare se il verbo rappresenta un fatto che fa nascere una relazione fra due set di entità. • Verificare che non esistano relazioni duplicate o ingannevoli. • Definire la cardinalità delle relazioni. • Individuare eventuali attributi delle relazioni. 5) Disegno del diagramma entità-relazione. Ai set di entità, agli attributi e alle relazioni devono essere assegnati dei nomi rappresentativi della realtà che esprimono e non devono essere ambigui. 2.6 Utilità del diagramma Entità-Relazione Perché dovremmo essere interessati al modello dati di un sistema? In primo luogo perché le strutture di dati e le relazioni possono essere così complesse che vogliamo evidenziarle ed esaminarle indipendentemente dall’elaborazione che avrà luogo. In effetti, ciò è particolarmente vero quando il modello del sistema viene mostrato agli utenti esecutivi di livello superiore in un’organizzazione (ad esempio, i vicepresidenti o direttori di reparto). Tali utenti sono spesso interessati ai dati: quali dati servono per condurre gli affari? In che modo i dati sono correlati ad altri dati? Chi possiede i dati? A chi è consentito l’accesso ai dati? La risposta ad alcune di queste domande – ad esempio, l’accesso ai dati e l’identificazione dei proprietari – è fornita dai DA. Ogni volta che si inizia a costruire un nuovo sistema informativo, si ha bisogno di parlare con queste persone in modo da poter coordinare le proprie informazioni sul sistema col loro modello di informazioni globale a livello aziendale. Il diagramma entità-relazione è un utile strumento per svolgere tale conversazione. Si dovrà altresì conversare con il gruppo dei DBA, situato solitamente nel reparto di elaborazione dati (mentre i DA non vi appartengono necessariamente), il cui compito è quello di garantire che i database computerizzati siano organizzati, gestiti e controllati efficacemente. Quindi essi costituiscono spesso la squadra di implementazione che ha la responsabilità di prendere un modello I&T Informatica e Telecomunicazioni SpA 21 Progettazione database relazionali essenziale (cioè, un modello indipendente dalla tecnologia specifica) e convertirlo in un progetto di database fisico efficace ed efficiente per Oracle, Informix, DB2 o qualche altro sistema di gestione di database. Il diagramma di entità-relazione è un efficace strumento di modellamento per comunicare col gruppo di DBA. In base alle informazioni presentate dal diagramma E-R, il gruppo di amministrazione del database può iniziare a determinare i tipi di chiave o di indici o di puntatori che servono per accedere efficientemente ai record del database. Quindi il modello dei dati fornisce, oltre alla rappresentazione dei dati del sistema che si vuole gestire, un utile strumento di conversazione con gli altri gruppi di lavoro che interagiscono in un progetto. Ma esso riguarda esclusivamente dati e relazioni tra i dati, senza fornire alcuna informazione sulle funzioni che creano e utilizzano i dati. Queste informazioni sono fornite da un altro tipo di diagramma, chiamati Data Flow Diagram (DFD), che modellano le funzioni svolte da un sistema (vedi appendice A). 2.7 Altri modelli dati Prima dell’arrivo dei sistemi relazionali i DBMS si basavano su modelli reticolari o gerarchici che non sono altro che dei casi particolari del modello relazionale. Successivamente al modello relazionale sono arrivati i sistemi orientati agli oggetti e alla logica che costituiscono l’ultima tendenza nell’ambito dei modelli dati e ancora oggi non è disponibile uno standard che ne regoli la definizione. Anche se il modello entità-relazione è attualmente il più diffuso, in alcuni contesti, si possono adattare meglio i sistemi gerarchici e reticolari, però scegliere lo schema concettuale che offra la migliore efficienza può essere piuttosto difficile e richiede una profonda comprensione del progetto del modello desiderato. E’ da tenere comunque presente che esistono degli algoritmi che permettono di passare da uno schema di database di un modello dati ad un altro in modo più o meno semplice. Vediamo adesso brevemente gli altri suddetti modelli dati. 2.7.1 Modello dati reticolare A grandi linee il modello dati reticolare è un modello entità-relazione in cui le relazioni sono vincolate ad essere binarie e del tipo uno-a-molti. Tale vincolo consente di usare, per i dati, il modello di grafo orientato. Al posto di set di entità, il modello reticolare parla di tipo record logico. Un tipo record logico è il nome di un insieme di record, chiamati record logici. I record logici sono composti da campi con i quali vengono rappresentati gli equivalenti degli “attributi” del modello entità-relazione. Le “relazioni binarie uno-a-molti”, vengono chiamati collegamenti o link. Per rappresentare i tipi record e i loro collegamenti si disegna un grafo orientato, chiamato rete, che in realtà è un diagramma semplificato entità-relazione. I nodi corrispondono ai tipi di record logici, e gli archi rappresentano i collegamenti. I nodi e gli archi sono battezzati rispettivamente coi nomi dei loro tipo record logico e dei link. Gli archi sono orientati nella direzione uno-a-molti e sono percorribili in entrambe le direzioni. Il record logico che si trova nella direzione “uno” della relazione uno-a-molti si chiama owner mentre l’altro si chiama member (vedi fig. 2.11). I&T Informatica e Telecomunicazioni SpA 22 Progettazione database relazionali LEGA CALCIO è owner del link Squadre_calcio LEGA CALCIO Squadre_calcio SQUADRA è member del link Squadre_calcio e contemporaneamente owner del link Giocatori_squadra SQUADRE Giocatori_squadra GIOCATORI è member del link Giocaori_squadra GIOCATORI Fig. 2.11 Esempio di schema reticolare L’esempio precedente è un caso molto semplice di rete, uno schema più generico è mostrato nella figura 2.12. A B C D E Fig 2.12 Esempio di una struttura di rete 2.7.2 Modello dati gerarchico Nel modello dati gerarchico (sottoinsieme del modello reticolare) lo schema del database è vincolato ad essere costituito da una struttura ad albero (uno o più, foresta) nelle quali sono rappresentate bene le relazioni uno-a-molti ma non quelle molti-a-molti, quindi si adatta bene a certe realtà ma non a tutti i possibili contesti. Nel modello dati gerarchico vale ancora la terminologia del modello reticolare come ad esempio “tipo record logico” ma alcuni termini della teoria degli alberi si adattano meglio al caso, come ad esempio, l’owner è chiamato più comunemente padre e il member figlio. La restrizione fondamentale rispetto alle reti è che un tipo di record può essere figlio solo su un collegamento mentre un tipo di record può essere padre su più collegamenti (gerarchia). La figura 2.13 mostra un esempio di struttura gerarchica. I&T Informatica e Telecomunicazioni SpA 23 Progettazione database relazionali A B C D E Fig 2.13 Esempio di struttura gerarchica Al contrario del modello reticolare, nel modello gerarchico i collegamenti sono percorribili solo in un verso, da padre a figlio, ma questa limitazione può essere superata con delle tecniche particolari che portano all’introduzione di due nuovi oggetti “tipo record virtuali” e “tipo record combinati”. Essi, nel primo caso sono semplicemente dei puntatori, nel secondo, sono dei puntatori più dei dati, che permettono di arrivare direttamente al nodo di interesse senza passare dai nodi intermedi e creare dei cammini arbitrari tra alberi differenti. Queste tecniche permettono anche di gestire le relazioni molti-a-molti (fig. 2.14). Studenti (Nome, Indirizzo) Iscrizione (*Corso, Voto) Corsi (Istituto, Numero) *Studenti Fig. 2.14 Relazione molti a molti con record combinati (* indica i record virtuali) 2.7.3 Modelli orientati agli oggetti Nell’ambito dei DBMS successivi al modello relazionale un accenno particolare va fatto ai modelli object oriented (OO-DBMS). Essi hanno la capacità di un DBMS e insieme alla combinazione DML/Linguaggio host hanno le seguenti caratteristiche: • Oggetti complessi: avere la capacità di definire tipi di dati con strutture nidificate, • Incapsulamento dell’informazione: cioè la capactà di definire procedure che si applicano solo a oggetti di un determinato tipo e la possibilità di richiedere che tutti gli accessi a questi oggetti avvengano attraverso l’applicazione di una di queste procedure (viene occultata la struttura interna degli oggetti), I&T Informatica e Telecomunicazioni SpA 24 Progettazione database relazionali • Identità degli oggetti: capacità del sistema di distinguere due oggetti che sembrano gli stessi (componenti primitive uguali, ma indirizzo diverso), • Gerarchia di tipi: permettere ai tipi di avere dei sottotipi con caratteristiche proprie. Nella teoria dei sistemi object oriented un oggetto è un insieme di dati, più le procedure per operare su questi dati. In termini rigorosamente informatici, un oggetto è un tipo di dato astratto (Abstract Data Type – ADT) composto per l’appunto dai dati e dalle procedure per operare su di essi, e tale che l’unico accesso possibile avviene tramite queste procedure. Queste procedure vengono chiamate metodi e vengono attivati dai messaggi che corrispondono a chiamate di funzioni dei linguaggi di programmazione tradizionali. L’insieme di tutti i metodi forniti per un oggetto è detta la sua interfaccia o il protocollo di accesso. Una classe invece è l’implementazione di un tipo di dato astratto basata sui concetti di ereditarietà, incapsulazione e polimorfismo. Per ereditarietà si intende il meccanismo di derivazione delle caratteristiche tra le classi di oggetti. Mentre polimorfismo è la possibilità di definire con lo stesso nome procedure su oggetti diversi e gestire quindi variabili non tipizzate. Introduciamo adesso una notazione per definire la struttura degli oggetti, cioè il formato per i tipi. Notiamo prima di tutto che l’insieme di strutture ad oggetto definibili nel modello ad oggetti è molto simile all’insieme dei possibili schemi per i database record del modello gerarchico, è possibile definire il modo ricorsivo l’insieme dei tipi oggetti permessi. • Un ente di tipo elementare, ad esempio un intero, un reale, o stringa di caratteri, è di tipo oggetto. Un tale tipo corrisponde al tipo di dato per un “campo” nelle reti o nelle gerarchie. • Se T è un tipo oggetto, allora SETOF(T) è un tipo oggetto. • Se T1, … , Tk sono tipi oggetto allora RECORDOF(T1, … , Tk) è un tipo oggetto. Facciamo un esempio. Supponiamo per semplicità che i soli tipi elementari siano string e integer. Allora un tipo di un prodotto può essere rappresento dal record: TipoProd = RECORDOF(nome:string, NumProd:integer) dove i campi del record sono stati rappresentati dalla coppia (<nomecampo>:<tipo>). Se vogliamo gestire gli ordini, dobbiamo rappresentare le coppie prodotto/quantità, allora necessitiamo creare il seguente tipo di oggetto: PQTipo = RECORDOF(prodotto:TipoProd, quant:integer) In questo caso il primo campo è un oggetto di tipo non elementare, e va pensato come un puntatore a un prodotto. Adesso possiamo definire il tipo di un ordine come: TipoOrd = RECORDOF(NumOrd:integer, comprende:SETOF(PQTipo)) Da notare all’interno della definizione di TipoOrd vi è quella di un altro tipo di oggetto, comprende. SETOF(PQTipo) è equivalente alla due dichiarazioni: SPTipo = SETOF(PQTipo) TipoOrd = RECORDOF(NumOrd:integer, comprende:SPQTipo) Uno schema di database per un ipotetico DB per un negozio è rappresentato nella figura 2.15. I&T Informatica e Telecomunicazioni SpA 25 Progettazione database relazionali TipoProd = RECORDOF(nome:string, NumProd:integer) PQTipo = RECORDOF(prodotto:TipoProd, quant:integer) TipoOrd = RECORDOF(NumOrd:integer, comprende:SETOF(PQTipo)) TipoCli RECORDOF(nome:string, indir:string, saldo:integer, ordini:SETOF(TipoOrd)) TipoRep = RECORDOF(nome:string, nemrep=integer, dipendenti:SETOF(TipoDip), capo:TipoDip, prodotti:SETOF(TipoProd)) TipoDip = RECORDOF(nome:string, stipendio:integer, reparto:TipoRep) PrezzoProd = RECORDOF(prodotto:TipoProd, prezzo:integer) TipoForn = RECORDOF(nome:string, indir:string, fornisce:SETOF(PrezzoProd)) Fig. 2.15 Esempio di schema di DB di un modello orientato agli oggetti 2.7.4 Modelli basati sulla logica Alcuni sistemi chiamati Knowledge Base Management Systems (KBMS) si basano su regole logiche o conoscenza. Un sistema KBMS è il risultato dell’integrazione di un DBMS e della tecnologia dell’intelligenza artificiale (AI). I modelli e la tecnologia dei DB attuali, in particolare quella relazionale, non sono appropriate per questa integrazione. Si è quindi studiata una nuova tecnologia e nuovi modelli di cui necessita introdurre alcune definizioni. Una base di conoscenza è un insieme strutturato di: • Dati rappresentanti i fatti circa gli aspetti del dominio del discorso che si vuole modellare (alcune volte chiamato extensional database o fact base), e • Conoscenza che rappresenta un alto livello di interpretazione e comprensione del dominio del discorso (alcune volte chiamato intensional database o rule base). Un knowledge base management system è uno strumento il quale fornisce: • Funzionalità per operare sia sull’intensional che sull’extensional database, • Un linguaggio che permetta di accedere alla base di conoscenza, e • Meccanismi per l’applicazione della conoscenza ai dati per ottenere risposte a delle richieste di ragionamento circa i fatti. Nei modelli dati basati sulla logica uno schema di database (o semplicemente schema) è definito come la coppia (IDB, IC) dove IDB è l’intensional database e IC è un insieme finito di regole chiamate vincoli di integrità (o semplicemente integrità). I vincoli usualmente esprimono informazioni in forma negativa che restringono l’ammissibilità delle informazioni del database. Per uno schema (IDC, IC), uno stato del database e una tripla (IDB, IC, EDB) dove EDB è l’extensional database. Vediamo adesso alcune necessarie definizioni sulle regole logiche. I&T Informatica e Telecomunicazioni SpA 26 Progettazione database relazionali Un predicato è una funzione booleana (risultato vero o falso) costituito da un nome e da un insieme di argomenti. Gli argomenti possono essere costituiti da costanti, variabili e simboli di funzioni. Le funzioni forniscono come risultato valori del tipo da noi scelto. Le regole logiche sono delle istruzioni logiche del tipo: “se A1 e A2 e … An sono vere, allora B è vera” e si scrive: B :- A1 & A2 & … & An. il simbolo “:-“ si legge “se”. Le regole logiche forniscono informazioni sui dati del database ed è utile notare l’analogia tra nozione logica di predicato coi sui argomenti e il nome di relazione con i suoi attributi. Cioè possiamo pensare che un predicato sia vero in corrispondenza dei suoi argomenti, se e solo se tali argomenti formano una tupla della relazione corrispondente. Vista la brevità della trattazione invece di continuare con il formalismo introduciamo qualche esempio. Supponiamo di avere uno schema di relazione Impiegati con attributi Nome, Ufficio, Stipendio e Indirizzo. Possiamo definire una vista pertutti attraverso la regola logica: pertutti(N, U, I) :- impiegati(N, U, S, I). La regola afferma che per tutti i nomi degli impiegati N, uffici U e indirizzo I, (N, U, I) è una proprietà del predicato pertutti se esiste uno stipendio S tale che (N, U, S, I) sia un’istanza del predicato impiegati. Notare che in generale una variabile come S, che compare alla destra del simbolo” :-“, ma non alla sua sinistra, è trattata come esistenzialmente quantificata, quindi la regola si legge “esiste qualche S”, dopo aver detto il “se” che corrisponde al simbolo “:-“. Vediamo un altro esempio di come sia possibile esprimere in termini logici le informazioni sui dati: supponiamo di avere la relazione Impiegati con i soli attributi Nome e Uff. e la relazione Uffici con gli attributi Uff. e Capo. Possiamo allora definire il predicato capo_di(I, C) col significato intuitivo che il capo C comanda l’impiegato I, espresso da: capo_di(I, C) :- impiegati(I, U) & uffici(U, C). (2.1) Cioè (I, C) è una istanza di capo_di tale per cui esiste un ufficio U tale che (I, U) sia un’istanza di impiegati e (U, C) una di uffici. In sostanza abbiamo usato la precedente regola logica per creare la vista capo_di che è analoga a una relazione con gli attributi nome e capo. La ricercare del capo dell’impiegato Rossi Mario si esprimere in termini del predicato capo_di semplicemente come: capo_di(‘Rossi Mario’, X) (2.2) La ricerca dei valori di X che rendono vera la 2.2 si trovano con un algoritmo sostanzialmente identico a quello indicato in 2.3, ma la regola logica 2.1 ha un ruolo importante nel permettere al sistema di interpretare il significato dell’interrogazione. In senso generico possiamo dire che la 2.1 rappresenta la “conoscenza” a proposito della relazione capo_di. select capo from impiegati, uffici where impiegati.nome = ‘Rossi Mario’ and impiegati.uff = uffici.uff; I&T Informatica e Telecomunicazioni SpA (2.3) 27 Progettazione database relazionali Un esempio di schema di database è: impiegati(nome, uff) uffici(uff) capo(impieg, uff) EDB capo_di(I, C) :- impiegati (I, U) & capo(U, C) IDB icl :- impiegati(I, U) & NOT uffici(U) IC Dove abbiamo un unico predicato, capo_di, ed una unica regola di integrità, icl. Essa afferma che tutti gli impiegati devono appartenere ad un ufficio esistente. I&T Informatica e Telecomunicazioni SpA 28 Progettazione database relazionali 3 Progettazione logica Nel secondo capitolo abbiamo visto i vari modelli dati che rappresentano il progetto di un database a livello concettuale. Per ogni modello a livello concettuale corrisponde un modello dati a livello logico della progettazione. In questo caso i modelli dati devono fornire oltre alla notazione per descrivere i dati anche un insieme di operazioni per manipolare i dati stessi. In questo capitolo vedremo il modello dati relazionale, nel quale solitamente viene tradotto il “diagramma entità-relazione” progettato in precedenza, e l’algebra relazionale, un formalismo che ci permette di accedere ai dati. Inoltre, illustreremo uno strumento di analisi della qualità di un progetto, la teoria della normalizzazione. 3.1 Modello dati logico Un modello dati a livello logico di progettazione è definito come un formalismo matematico composto da due parti: • una notazione per descrivere i dati, • un insieme di operazioni per manipolare i dati. Un modello matematico dei dati consente l’utilizzo di linguaggi e metodologie formali per l’accesso ai dati. In particolare le due metodologie su cui si basano i linguaggi di accesso ai dati di un database relazionale sono l’algebra relazionale e il calcolo relazionale. In seguito verrà introdotta la prima metodologia, in quanto costituisce la base del linguaggio SQL (Structured Query Language), ormai affermato come standard nell’accesso ai database relazionali. 3.2 Modello dati relazionale La rappresentazione dei dati nel modello logico relazionale è basata su un unico concetto fondamentale, ovvero la relazione: questa va intesa in termini algebrici, e non va confusa con le relazioni tra i dati del modello concettuale. Il concetto di relazione algebrica è quello secondo la teoria degli insiemi, cioè un sottoinsieme del prodotto cartesiano di una lista di domini. Formalmente un dominio è semplicemente una lista di valori, non diverso da un tipo di dato. Il prodotto cartesiano dei domini D1, D2, … , Dk che si scrive D1xD2x … xDk è l’insieme di tutte le k-tuple (v1, v2, … , vk) tali che v1 sia in D1, v2 in D2 e così via. Ad esempio se k=2, D1={0,1} e D2={a, b, c}, allora: D1xD2={(0, a), (0, b), (0, c), (1, a), (1, b), (1, c)} Una relazione R è un qualunque sottoinsieme del prodotto cartesiano di uno o più domini. Ad esempio, considerando il prodotto cartesiano precedente, {(0, a), (0, c), (1, b)} è una relazione così come l’insieme vuoto. Gli elementi di una relazione si chiamano tuple o record. Ogni relazione che sia un sottoinsieme di qualche prodotto D1xD2x … xDk di k domini si dice che k è il grado (o arità) della relazione R. Una I&T Informatica e Telecomunicazioni SpA 29 Progettazione database relazionali tupla (v1, v2, … , vk) ha k componenti e con vi indichiamo la i-esima componente. Una tupla con k componenti è anche chiamata k-tupla. Vediamo un esempio più esemplificativo di relazione. Consideriamo i domini: Codice_Articolo = {T100, T200} Descriz_Articolo = {Tavolo quadrato, Tavolo tondo} una possibile relazione tra essi è: Tavoli = {(T100, Tavolo tondo), (T200, Tavolo quadrato)} Per comodità di rappresentazione è più conveniente descrivere una relazione algebrica come una tabella come fatto in figura 3.1. Attributi Schema di relazione Art_Cod Art_Descriz T100 Tavolo tondo T200 Tavolo quadrato Tupla o record Tabella/Relazione Tavoli Componente della tupla o campo del record Fig. 3.1 Rappresentazione tabellare di una relazione Nella tabella che rappresenta la relazione algebrica, ogni riga è una tupla (o record) e a ogni colonna corrisponde una componente (o campo). Alle colonne si danno spesso dei nomi e sono gli attributi. L’insieme dei nomi di attributi (delle colonne) di una relazione si chiama schema di relazione. Se denotiamo con REL una relazione e il suo schema di relazione ha gli attributi A1, A2, … , Ak si scrive spesso lo schema di relazione come: REL(A1, A2, … , Ak) per l’esempio precedente scriveremo: Tavoli(Art_Cod, Art_Descriz) L’insieme degli schemi di relazione usati per rappresentare informazioni viene chiamato schema di database (relazionale), e i valori correnti delle corrispondenti relazioni formano un’istanza del database o semplicemente il database (relazionale). Nella definizione di relazione come insieme seguono due osservazioni fondamentali: • in una tabella non possono esistere due righe uguali • l’ordine tra le righe di una tabella non è significativo. I&T Informatica e Telecomunicazioni SpA 30 Progettazione database relazionali Da tali osservazioni deriva che è possibile, e necessario, individuare in ciascuna tabella un insieme di attributi (colonne) in base alle quali identificare le singole righe, che rappresentano quindi una chiave di accesso univoca alle informazioni contenute nella tabella stessa. Questo insieme di colonne, che va definito in fase di creazione dello schema logico, è detto chiave primaria (Primary Key - PK) della tabella. 3.3 Rappresentazione dei diagrammi entità-relazione nel modello relazionale Per la creazione di uno schema logico relazionale è necessario, partendo da uno schema concettuale definito in precedenza, in base al modello entità-relazione, applicare le seguenti regole. 1) Le entità dello schema concettuale diventano tabelle nello schema logico. 2) Le relazioni tra entità dello schema concettuale, vengono rappresentate nello schema logico, facendo uso delle cosiddette chiavi esterne. Una chiave esterna (Foreign Key - FK) di una tabella è un insieme di attributi che corrispondono a quelli che costituiscono la chiave primaria di un’altra tabella, e stabiliscono quindi, un riferimento tra le righe delle due tabelle (vincoli di integrità referenziale, vedi par. 3.5). In particolare per rappresentare una relazione tra le tabelle T1 e T2 bisogna distinguere tra le relazioni 1:1, 1:N, N:N. 2.1) Relazione 1:1 Agli attributi di T1 vanno aggiunti, come chiave esterna, gli attributi che costituiscono la chiave primaria di T2, o alternativamente a T2 vanno aggiunti, come chiave esterna, gli attributi che costituiscono la chiave primaria di T1. Le due soluzioni sono del tutto equivalenti. 2.2) Relazione 1:N Supponiamo che la relazione sia 1:N tra T1-T2. Agli attributi di T2 vanno aggiunti, come chiave esterna, gli attributi che costituiscono la chiave primaria di T1 (ma non il viceversa!). 2.3) Relazione N:N In questo caso va definita una nuova tabella T3, che contiene, come chiavi esterne, le chiavi primarie sia di T1 che di T2; è da notare come in questo caso la chiave primaria della tabella T3 possa essere costituita dalla totalità dei suoi attributi. Gli eventuali attributi della relazione vengono inclusi come attributi della tabella in cui è rappresentata la relazione (T3), quella che contiene le chiavi esterne. 3.3.1 Eliminazione delle gerarchie Il modello relazionale non permette di rappresentare direttamente le gerarchie Isa del modello E-R quindi vanno eliminate ristrutturando entità e relazioni con tre alternative possibili che vediamo rispettivamente nella figura 3.2 b), c), d) in relazione alla generica gerarchia Isa della figura 3.2 a). 1) Accorpamento delle figlie della generalizzazione nel padre. Le entità E1 ed E2 vengono eliminate e le loro proprietà (attributi e partecipazione a relazioni e generalizzazioni) vengono aggiunte all’entità padre E0. A tale entità viene aggiunto un ulteriore attributo che serve a distinguere il “tipo” di una occorrenza di E0, cioè se tale occorrenza apparteneva a E1 o a E2 (fig. 3.2 b). I&T Informatica e Telecomunicazioni SpA 31 Progettazione database relazionali A01 A02 E0 Isa Isa E1 E2 A11 A21 R1 E3 R2 E4 A01 A02 A11 a) Generica gerarchia Isa E0 A21 R1 E3 R2 E4 Tipo b) Accorpamento figlie al padre R11 R12 E3 A01 E1 A02 E2 R E4 A11 A01 A21 A02 A01 A02 c) Accorpamento padre nelle figlie E0 RG1 RG2 E1 E2 A11 A21 R1 E3 R2 E4 d) Sostituzione gerarchia Isa con relazioni 1:1 Fig. 3.2 Ristrutturazione gerarchia Isa I&T Informatica e Telecomunicazioni SpA 32 Progettazione database relazionali 2) Accorpamento del padre della generalizzazione nelle figlie. L’entità padre E0 viene eliminata e, per la proprietà dell’ereditarietà, i suoi attributi, il suo identificatore e le relazione a cui tale entità partecipava, vengono aggiunti alle entità figlie E1 ed E2. Le relazioni R11 e R12 rappresentano rispettivamente la restrizione della relazione R1 sulle occorrenze delle entità E1 ed E2 (fig. 3.2 c)). 3) Sostituzione della generalizzazione con relazioni 1:1. La generalizzazione si trasforma in due associazioni uno a uno che legano rispettivamente l’entità padre con le entità figlie E1 ed E2. Non ci sono trasferimenti di attributi o associazioni e le entità E1 ed E2 sono identificate esternamente dall’entità E0 (fig 3.2 d)). Nello schema ottenuto bisogna verificare, dopo ogni operazione di aggiornamento delle entità coinvolte nella generalizzazione, che per ogni occorrenza di E1 e di E2 esista una occorrenza di E0 collegata (e per le generalizzazioni totali, che per ogni occorrenza di E0 c’è una occorrenza collegata in E1 o E2). I&T Informatica e Telecomunicazioni SpA 33 Progettazione database relazionali 3.4 Schema logico del database di esempio Trasformiamo adesso lo schema concettuale del database Mobili Componibili, sviluppato nel capitolo precedente, nel corrispondente schema logico secondo il modello relazionale seguendo le regole sopra descritte. I passi per tradurre lo schema concettuale nello schema logico corrispondente sono i seguenti. 1) Per ciascun insieme di entità dello schema concettuale, viene definita una tabella nello schema logico: Categorie, Articoli, Componenti, Laboratori, Negozi e Ordini (vedi figura 3.3). I nomi delle entità nello schema concettuale sono espressi al singolare (Categoria, Articolo,… ); nello schema logico sono stati resi al plurale, seguendo una convenzione spesso adottata (Categorie, Articoli,… ). Si sarebbe potuto comunque cambiare completamente i nomi o lasciare gli stessi; ciò che importa è avere come obiettivo la comprensibilità dello schema. Categorie Cat_Cod Cat_Descrizione Articoli Art_Cod Art_Descrizione Art_Prezzo Art_Iva Art_Spese_Trasporto Componenti Com_Cod Com_Descrizione Com_Costo Lab_Indirizzo Lab_Città Laboratori Lab_Cod Lab_Telefono Negozi Neg_Cod Neg_Nome Neg_Indirizzo Neg_Città Neg_Telefono Ordini Ord_Cod Ord_Data Fig. 3.3 Le tabelle corrispondenti ai set di entità del database Mobili Componibili I&T Informatica e Telecomunicazioni SpA 34 Progettazione database relazionali 2) Per ciascuna tabella viene definita una chiave primaria che ne identifica univocamente le righe (figura 3.4). Tabella Chiave primaria Categorie Articoli Componenti Laboratori Negozi Ordini Cat_Cod Art_Cod Com_Cod For_Cod Neg_Cod Ord_Cod Fig. 3.4 Tabelle con relative chiavi primarie 3) Vengono definite le chiavi esterne per la rappresentazione delle relazioni 1:N tra Categorie e Articoli, tra Negozi e Ordini e tra Laboratori e Componenti, figura 3.5. Alla tabella Articoli è stato aggiunto Cat_Cod, la chiave primaria della tabella Categorie; a Ordini è stata aggiunto Neg_Cod, la chiave primaria di Negozi; analogamente a Componenti è stato aggiunto Lab_Cod, la chiave primaria di Laboratori. Articoli Art_Cod Cat_Cod Art_Descrizione Art_Presso Art_Iva Art_Spese_Trasporto Ordini Ord_Cod Neg_Cod Ord_Data Lab_Cod Com_Descrizione Componenti Com_Cod Com_Costo Fig. 3.5 Tabelle del database Mobili Componibili con le chiavi esterne per le relazioni 1:N 4) Vengono definite le nuove tabelle CompArt e OrdArt per la rappresentazione delle relazioni N:N tra Componenti e Articoli e tra Ordini e Articoli (figura 3.6). La tabella CompArt contiene le chiavi primarie di Componenti e Articoli, la tabella OrdArt contiene le chiavi primarie di Ordini e Articoli. Si è poi aggiunto in CompArt l’attributo CompArt_Qta che specifica la quantità necessaria di un componente nella costruzione di un articolo. Per esempio, se l’articolo è una libreria e il I&T Informatica e Telecomunicazioni SpA 35 Progettazione database relazionali componente è uno scaffale, CompArt_Qta rappresenta il numero di scaffali necessari per costruire la libreria. Analogamente si procede per OrdArt. CompArt Art_Cod Com_Cod CompArt_Qta Art_Cod OrdArt_Qta OrdArt Ord_Cod Fig 3.6 Rappresentazione delle relazioni N:N nel database Mobili Componibili In figura 3.7 viene mostrata una rappresentazione dello schema logico relazionale del database di esempio Mobili Componibili. I&T Informatica e Telecomunicazioni SpA 36 Progettazione database relazionali Negozi Neg_Cod Neg_Nome Neg_Indirizzo Neg_Città Neg_Telefono 1 Ordini Ord_Cod Neg_Cod Ord_Data N 1 N OrdArt Ord_Cod Art_Cod OrdArt_Qta N 1 Categorie Cat_Cod Cat_Descrizione 1 Articoli Art_Cod Cat_Cod Art_Descrizione Art_Prezzo Art_IVA Art_Spese_Trasporto N 1 N 1 CompArt Art_Cod Com_Cod CompArt_Qta N N 1 Laboratori Lab_Cod Lab_Indizzo Lab_Città Lab_Telefono 1 N Componenti Com_Cod Lab_Cod Com_Descrizione Com_Costo Fig. 3.7 Rappresentazione dello schema logico relazionale del database Mobili Componibili I&T Informatica e Telecomunicazioni SpA 37 Progettazione database relazionali 3.5 Vincoli di integrità Le strutture del modello relazionale ci permettono di organizzare le informazioni di interesse per le nostre applicazioni. In molti casi, però, non è vero che qualsiasi insieme di tuple sullo schema rappresenti informazioni corrette per l’applicazione. A tale scopo è stato introdotto il concetto di vincolo di integrità, come proprietà che deve essere soddisfatta dalle istanze che rappresentano informazioni corrette per l’applicazione. E’ possibile classificare i vincoli a seconda degli elementi di una base di dati che ne sono coinvolti. Distinguiamo due categorie, la prima delle quali ha alcuni casi particolari: • Un vincolo è intrarelazionale se il suo soddisfacimento è definito rispetto a singole relazioni della base di dati: • Un vincolo di tupla è un vincolo che può essere valutato su ciascuna tupla indipendentemente dalle altre. • Come caso più specifico, un vincolo definito con riferimento a singoli valori viene detto vincolo su valori o vincolo di dominio, in quanto impone una restrizione sul dominio degli attributi. Ad esempio, se una componente di una tupla rappresenta il voto di un esame universitario in esso sono ammessi valori compresi tra 18 e 30. • Un vincolo è interrelazionale se coinvolge più relazioni. Ad esempio se abbiamo una tabella Esami e una Studenti possiamo richiedere che un numero di matricola compaia nella relazione Esami solo se compare nella relazione Studenti. 3.5.1 Vincoli di chiave I vincoli di chiave sono i più importanti vincoli intrarelazionali. Nel modello relazionale ogni relazione deve possedere una chiave e tale chiave deve identificare univocamente tutte le tuple della relazione a cui afferisce. Anche se è permesso che delle tuple possano contenere valori nulli (NULL) che indicano l’assenza (o la non conoscenza) dell’informazione per il corrispondente componente, sulle chiavi delle relazioni è vietata la presenza dei valori nulli pena l’identificazione stessa delle tuple. 3.5.2 Vincoli di integrità referenziale I vincoli di integrità referenziale sono la più importante classe di vincoli interrelazionali. Vediamo alcune caratteristiche con un esempio: consideriamo la base di dati della figura 3.8. In essa la prima relazione contiene informazioni relative ad un insieme di infrazioni al codice della strada, la seconda agli agenti di polizia che le hanno rilevato e la terza ad un insieme di autoveicoli. Le informazioni della relazione INFRAZIONI sono rese significative e complete attraverso il riferimento alle altre due relazioni: alla relazione AGENTI, per il tramite dell’attributo Agente, che contiene i numeri di matricola di agenti corrispondenti alla chiave primaria della relazione AGENTI, e alla relazione AUTO per mezzo degli attributi Prov e Targa, che contengono gli omonimi attributi che formano la chiave primaria della relazione AUTO. I riferimenti sono significativi in quanto i valori nella relazione INFRAZIONI sono uguali a valori effettivamente presenti nelle altre due: se un valore di Agente in INFRAZIONI non compare come valore della chiave di AGENTI, allora il riferimento non è efficace. Nell’esempio, tutti i riferimenti sono in effetti utilizzabili. Un vincolo di integrità referenziale (foreign key o referential integrity constraint) fra un insieme di attributi X di una relazione R1 e un’altra relazione R2 è soddisfatto se i valori di X di ciascuna tupla dell’istanza di R1 compaiono come valori della chiave (primaria) dell’istanza R2. I&T Informatica e Telecomunicazioni SpA 38 Progettazione database relazionali INFRAZIONI Codice 143256 987554 987554 630876 539856 Data 25/10/92 26/10/92 26/10/92 15/10/92 12/10/92 Agente 567 456 456 456 567 Art 44 34 34 53 44 Prov RM RM RM MI MI Numero 4E5432 4E5432 2F7643 2F7643 2F7643 Tabella secondaria (correlata) FK FK PK Matricola 567 456 638 CF RSSM … NREL … NREP … AGENTI Cognome Rossi Neri Neri Tabella primaria Nome Mario Luigi Piero PK Prov RM RM RM MI AUTO Numero Proprietario 2F7643 Verdi Piero 1A2346 Verdi Piero 4E5432 Bini Luca 2F7643 Luci Gino Tabella primaria Indirizzo Via Tigli Via Tigli Via Aceri Via Aceri Fig. 3.8 Una base di dati con vincoli di integrità referenziale Una istanza del database precedente che non rispetta i vincoli di integrità referenziale è mostrato in figura 3.9. INFRAZIONI Codice 987554 630876 Data 26/10/92 15/10/92 Agente 456 456 Art 34 53 Prov RM FI Numero 2F7643 4E5432 FK FK PK Matricola 567 638 CF RSSM … NREP … AGENTI Cognome Rossi Neri Nome Mario Piero PK Prov RM FI MI Numero 1A2346 4E5432 2F7643 AUTO Proprietario Indirizzo Verdi Piero Via Tigli Bini Luca Via Aceri Luci Gino Via Noci Fig. 3.9 Una base di dati che viola i vincoli di integrità referenziale La relazione AGENTI non contiene nessuna tupla con valore Matricola uguale a 456, poi AUTO non contiene nessuna tupla con valore “RM” su Prov e 2F7643 su Numero. I&T Informatica e Telecomunicazioni SpA 39 Progettazione database relazionali Quindi i vincoli di integrità referenziale stabiliscono delle regole da seguire per salvare le relazioni definite tra tabelle durante l’immissione o l’eliminazione di record. Quando si applica l’integrità referenziale non è possibile aggiungere un record ad una tabella correlata se nella tabella primaria non esistono record associati, modificare valori contenuti nella tabella primaria che genererebbero record isolati in una tabella correlata ed infine eliminare record della tabella primaria se in una tabella correlata sono inclusi dei record correlati corrispondenti. Non possiamo ad esempio cancellare un Agente dalla tabella AGENTI quando esistono ancora delle tuple corrispondenti nella tabella INFRAZIONI, e viceversa non possiamo inserire delle Infrazioni non correlati ad alcun record nella tabella AGENTI e AUTO. 3.6 Vantaggi del modello relazionale Nel modello relazionale, come visto nei paragrafi precedenti, i riferimenti tra le varie relazioni (tabelle) vengono realizzate mediante l’utilizzo di campi con domini comuni, questo si indica dicendo che il modello relazionale è “basato su valori”. Altri modelli logici, come il reticolare e il gerarchico, realizzano le corrispondenze in modo esplicito attraverso puntatori e vengono pertanto detti modelli “basati su record e puntatori”. La figura 3.10 mostra un database relazionale, mentre nella figura 3.11 è rappresentato lo stesso database in un modello ideale basato su record e puntatori, dove sono stati utilizzati puntatori al posto dei riferimenti realizzati tramite valori (i numeri di matricola degli studenti e i codici dei corsi). Matricola 276545 485745 200768 587614 937653 STUDENTI Cognome Nome Rossi Maria Neri Anna Verdi Fabio Rossi Luca Bruni Mario Studente 276545 276545 937653 200768 Codice 01 03 04 ESAMI Voto 28 27 25 24 CORSI Titolo Analisi Chimica Chimica Data di nascita 25/11/1971 13/04/1972 12/02/1972 10/10/1971 01/12/1971 Corso 01 04 01 04 Docente Giani Melli Belli Fig. 3.10 Un database relazionale I&T Informatica e Telecomunicazioni SpA 40 Progettazione database relazionali Matricola 276545 485745 200768 587614 937653 STUDENTI Cognome Nome Rossi Maria Neri Anna Verdi Fabio Rossi Luca Bruni Mario Studente ESAMI Voto 28 27 25 24 Data di nascita 25/11/1971 13/04/1972 12/02/1972 10/10/1971 01/12/1971 Corso CORSI Codice Titolo Docente 01 Analisi Giani 03 Chimica Melli 04 Chimica Belli Fig. 3.11 Database della fig. 3.10 con puntatori Rispetto ad un modello basato su record e puntatori, il modello relazionale, basato su valori, presenta diversi vantaggi: • Esso richiede di rappresentare solo ciò che è rilevante dal punto di vista dell’applicazione (dell’utente); i puntatori sono qualcosa di aggiuntivi, legato ad aspetti realizzativi; nei modelli con puntatori, il programmatore delle applicazioni fa riferimento a dati che non sono significativi per l’applicazione; • Essendo tutta l’informazione contenuta nei valori, è relativamente semplice trasferire i dati da un contesto ad un altro (per esempio se si deve trasferire una base di dati da un calcolatore ad un altro); in presenza di puntatori l’operazione è più complessa, perché i puntatori hanno un significato locale al sistema, che non sempre è immediato esportare; • La rappresentazione logica dei dati (costituita dai soli valori) non fa alcun riferimento a quella fisica, che può anche cambiare nel tempo: il modello relazionale permette quindi di ottenere l’indipendenza fisica dei dati. A titolo di inciso, vale la pena notare che anche in una base di dati relazionale, a livello fisico, i dati possono essere rappresentati secondo modalità che prevedono l’uso di puntatori. La differenza, rispetto ai modelli su puntatori è nel fato che qui i puntatori non sono visibili a livello logico. Inoltre, da notare anche database moderni, come quelli orientati agli oggetti, vengono introdotti gli identificatori (di oggetti), che, pur ad un livello di astrazione più alto, presentano alcune delle caratteristiche dei puntatori. I&T Informatica e Telecomunicazioni SpA 41 Progettazione database relazionali 3.7 Algebra relazionale Gli operatori dell’algebra relazionale permettono di eseguire le operazioni sui dati di un database relazionale. Essi definiscono le operazioni rilevanti nella gestione delle tabelle (relazioni algebriche) e possono essere classificati in operatori di base e operatori derivati. I primi costituiscono un insieme funzionalmente completo, ovvero permettono di realizzare tutte le operazioni di dati all’interno di uno di schema relazionale. I secondi sono derivabili dai primi mediante opportune operazioni algebriche a volte complesse. Gli operatori di base sono proiezione, selezione, prodotto, ridenominazione, unione e differenza. Gli operatori derivati sono intersezione, giunzione naturale e giunzione. Tutti gli operatori relazionali hanno la caratteristica comune di avere come argomento delle relazioni (tabelle) e fornire come risultato altre relazioni (ancora tabelle). Nel seguito saranno usati come sinonimi i termini relazione e tabella. 3.7.1 Operatori di base 3.7.1.1 Proiezione Data una tabella e un insieme di attributi, la proiezione restituisce una tabella con tutte le righe di quella di partenza ma con alcune colonne (attributi) eliminati e/o risistemati nell’ordine desiderato (fig.3.12 c) e 3.13). X Y Z Proiezione X Y 3.7.1.2 Selezione o restrizione Data una tabella e una condizione logica sui suoi attributi, la selezione restituisce una tabella con gli stessi attributi di quella di partenza ma con le sole righe che soddisfano la condizione (fig. 3.12 d) e 3.13). X Y Z Selezione X Y Z 3.7.1.3 Prodotto (cartesiano) o congiunzione Date due tabelle, il loro prodotto restituisce una tabella le cui righe sono ottenute concatenando ogni riga della prima con tutte le righe della seconda (fig. 3.12 e)). 3.7.1.4 Ridenominazione Data una tabella e una sequenza di attributi, la ridenominazione restituisce una tabella ottenuta dalla tabella di partenza cambiandone tutti gli attributi ordinatamente in quelli della sequenza data come argomento. Espressa in altri termini, la ridenominazione di una tabella in base a un insieme di nomi consente di ridenominarne le colonne assegnando loro tali nomi. 3.7.1.5 Unione Date due tabelle con gli stessi attributi restituisce come risultato una tabella contenente tutte le righe delle due tabelle considerate (fig. 3.12 f)). 3.7.1.6 Differenza Anche in questo caso le tabelle devono avere la stessa struttura; il risultato è una tabella che contiene tutte le righe della prima escluse quelle contenute nella seconda. In altre parole la tabella restituita è uguale alla prima tabella epurata dalle righe uguali, cioè contenente gli stessi valori, a righe presenti nella seconda tabella (fig. 3.12 g)). I&T Informatica e Telecomunicazioni SpA 42 Progettazione database relazionali A B a d c C b a b D c f d E b d F g a a f b) Relazione S a) Relazione R A C a d c A c f d A B b b a a b b C b b c d d) Selezione su R con condizione logica B=b c) Proiezione di R sugli attributi A e C a a d d c c B a c C c c f f d d D b d b d b d E F g a g a g a a f a f a f e) Prodotto cartesiano R x S a d c b b a b g c f d a a c b b c d g) Differenza delle relazioni R e S, R – S. f) Unione delle relazioni R e S, R ∪ S. Fig. 3.12 Alcune operazioni dell’algebra relazionale SELECT nome FROM clienti WHERE saldo < 0; Fig 3.13 Implementazione delle operazioni di PROIEZIONE e SELEZIONE in SQL. La parola chiave SELECT in SQL corrisponde alla proiezione (e non alla selezione, fare attenzione all’infelice conflitto di notazione). Mentre la selezione viene implementata in SQL con la clausola WHERE. I&T Informatica e Telecomunicazioni SpA 43 Progettazione database relazionali 3.7.2 Operatori derivati 3.7.2.1 Intersezione Date due tabelle con gli stessi attributi, restituisce come risultato una tabella contenente tutte le righe comuni alle due tabelle considerate. L’intersezione può essere espressa con due operazioni di differenza: R ∩ S = R – (R – S) 3.7.2.2 Natural join (giunzione naturale) Date due tabelle con un dominio in comune, restituisce una tabella ottenuta mediante il seguente procedimento: 1) viene effettuato il prodotto cartesiano tra le due tabelle; 2) sulla tabella così risultante viene eseguita la selezione delle righe in cui gli attributi appartenenti al dominio comune sono uguali; 3) vengono infine ridenominati gli attributi comuni con uno stesso nome, in modo che compaiono una sola volta. E’ possibile definire il natural join anche tra tabelle aventi più domini in comune. Se le tabelle non hanno domini in comune il natural join si riduce al prodotto cartesiano. 3.7.2.3 Join (giunzione) Date due tabelle con un dominio in comune, ed una condizione nella forma A1 op A2 Dove A1 e A2 sono gli attributi delle due tabelle corrispondenti al dominio in comune e op è un operatore di confronto (>, <, ≤, ecc.), la join restituisce una tabella ottenuta mediante il seguente procedimento: 1) viene effettuato il prodotto cartesiano tra le due tabelle: 2) sulla tabella così risultante viene eseguita la selezione delle righe in cui gli attributi appartenenti al dominio comune soddisfano la condizione: 3) vengono infine ridenominati gli attributi comuni con lo stesso nome, in modo che compaiono una volta sola. Se op è l’operazione di = la join viene chiamata equijoin. 3.7.2.4 Semijoin Il semijoin della relazione R con la relazione S è la proiezione sugli attributi di R del natural join di R e S (fig. 3.14 h)). I&T Informatica e Telecomunicazioni SpA 44 Progettazione database relazionali A a d b c B b b b a C B c c f d C b b a c c d D d e b b) Relazione S A a a d d c B b b b b a C c c c c d D d e d e b a) Relazione R d) Natural join tra R e S (attributi in comune B e C) A 1 4 7 B 2 5 8 C D 3 6 9 3 6 E 1 2 A 1 1 4 B 2 2 5 C 3 3 6 D 3 6 6 E 1 2 2 f) Relazione U e) Relazione T A a d c g) Join B<D tra le relazioni T e U B b b a C c c d h) Semijoin di R e S (proiezione su A, B, C del natural join in fig. d)) Fig. 3.14 Natural join, join, semijoin I&T Informatica e Telecomunicazioni SpA 45 Progettazione database relazionali 3.8 Normalizzazione dei dati Una volta impostato uno schema logico relazionale è necessario effettuare una serie di verifiche sulla correttezza del procedimento svolto. Queste potranno portare a modificare la struttura dello schema stesso, al fine di renderlo corretto ed evitare il verificarsi, nella gestione dei dati, di errori difficilmente ovviabili a posteriori. Tale processo è detto normalizzazione dello schema relazionale ed è effettuabile mediante procedimenti di tipo algebrico, basati sui concetti di dipendenza e di scomposizione. Esistono cinque forme normali di cui le prime due sono molto semplici mentre quelle più significative sono la terza e quella di Boyce-Codd che hanno certe proprietà desiderabili: • assenza o quasi di ridondanza nelle relazioni • eliminazione delle anomalie • conservazione delle dipendenze • ricostruzione della relazione di partenza a partire da quelle scomposte • mantenimento dei vincoli di integrità del progetto originale. 3.8.1 Ridondanza e anomalie Vediamo dei comportamenti poco desiderabili di uno schema di relazione tramite un esempio. Supponiamo di avere la relazione: INFO_FORN(NOME_FORN, INDIR_FORN, NOME_PROD, PREZZO) che comprende tutte le informazioni di un fornitore di un particolare prodotto. In questo schema si possono riscontrare diversi problemi. • Ridondanza. L’indirizzo del fornitore è ripetuto una volta per ogni prodotto venduto. • Inconsistenza potenziale (anomalie di aggiornamento). Come conseguenza della ridondanza potremmo aggiornare l’indirizzo del fornitore in una tupla, lasciandolo inalterato in un’altra. Non avremmo allora un unico indirizzo per ogni fornitore, come invece ci si aspetterebbe. • Anomalie di inserimento. Non possiamo registrare un indirizzo di un fornitore, se questo attualmente non fornisce almeno un prodotto. In una tupla potremmo porre dei valori nulli nelle componenti NOME_PROD e PREZZO per quel fornitore, ma allora, quando per esso si introducesse un prodotto, ci ricorderemmo di cancellare la tupla dei valori nulli? E ancora peggio, NOME_PROD e NOME_FORN insieme formano una chiave per la relazione, e non è ammissibile che si inseriscono dei valori nulli in una chiave. • Anomalie in cancellazione. L’inverso del problema precedente è che se cancellassimo tutti i prodotti di un fornitore, involontariamente perderemmo traccia del suo indirizzo. Nell’esempio mostrato tutti i problemi precedenti svaniscono se sostituiamo la relazione INFO_FORN con i due schemi di relazione seguenti: FORNITORI(NOME_FORN, INDIR_FORN) FORNISCE(NOME_FORN, NOME_PROD, PREZZO) In tal caso FORNITORI contiene l’indirizzo di ogni fornitore esattamente una volta, quindi non vi è ridondanza. Inoltre possiamo introdurre l’indirizzo di un fornitore anche se attualmente non fornisce prodotti. I&T Informatica e Telecomunicazioni SpA 46 Progettazione database relazionali Adesso però abbiamo lo svantaggio di dover eseguire una join tra le due relazione per ottenere gli indirizzi dei fornitori di un certo prodotto. Quello che abbiamo appena eseguito non è altro che una normalizzazione della relazione INFO_FORN scomponendo tale relazione in altre due relazioni che conservano tutti i dati e le dipendenze di partenza. Vediamo adesso brevemente i concetti dipendenze e di scomposizione che sono alla base delle forme normali. 3.8.2 Dipendenze La prima cosa da notare è che le dipendenze e la ridondanza sono strettamente legate tra di loro. Nel caso in cui le dipendenze siano funzionali, la forma della ridondanza è ovvia. Se nella precedente relazione INFO_FORN vedessimo le due tuple della figura 3.15: Nome_Forn Indir_Forn Nome_Prod Prezzo Acme Acme Via Roma 16 ??? Brie Spumante 3490 1190 Fig 3.15 Relazione con ridondanza potremmo fare l’ipotesi che Nome_Forn determini funzionalmente Indir_Forn per dedurre che ??? sta per Via “Roma 16”. Quindi la dipendenza funzionale fa si che per un fornitore, tutti i campi Indir_Forn, escluso il primo, siano ridondanti. Se però non sono valide le nostre ipotesi sulla dipendenza funzionale sopraddetta quest’ultimo campo non sarebbe ridondante. Quando abbiamo dei tipi di dipendenza più generali di quelle funzionali, la forma assunta dalla ridondanza diventa meno chiara. In tutti i casi però sembra che la causa e la cura della ridondanza vadano mano nella mano. Cioè la dipendenza, come quella tra Indir_Forn e Nome_Forn, non solo dà origine alla ridondanza, ma permette anche, la scomposizione della relazione Info_Forn in Fornitori e Fornisce, in modo tale che la relazione originale Info_Forn possa essere recuperata dalle due relazioni. Come evidenziato un tipo di dipendenza è quella funzionale, un’altra importante che analizzeremo è quella a molti valori. 3.8.2.1 Dipendenze funzionali Le dipendenze funzionali descrivono legami di tipo funzionale tra gli attributi di una relazione. Se ad esempio un attributo ne determina un altro in modo unico, come potrebbe essere che Nome_Fornitore determina Indirizzo_Fornitore diciamo che vi è una dipendenza funzionale di Indirizzo_Fornitore da Nome_Fornitore, o anche che Nome_Fornitore determina funzionalmente Indirizzo_Fornitore, e si indica come segue: {Nome_Fornitore} à {Indirizzo_Fornitore} Il significato delle dipendenze funzionali è che se abbiamo una relazione dove un certo insieme di attributi formano una chiave per tale relazione, possiamo dire che, gli altri attributi (anche un sottoinsieme della chiave) sono determinati funzionalmente dalla chiave. La chiave quindi determina funzionalmente una relazione. Un’altra dipendenza funzionale dello schema di relazione Info_Forn è: {Nome_Forn, Nome_Prod} à {Prezzo} I&T Informatica e Telecomunicazioni SpA 47 Progettazione database relazionali che ritroviamo nella seconda tabella della scomposizione. 3.8.2.2 Dipendenze a molti valori Introduciamo il concetto di dipendenza a molti valori con un esempio. Supponiamo di avere il seguente schema di relazione INFO_CORSO(CORSO, INSEGNANTE, ORA, AULA, STUDENTE, VOTO). In figura 3.16 abbiamo una possibile relazione per tale schema. Corso Cs101 Cs101 Cs101 Cs101 Cs101 Cs101 Insegnante Ora Chiarissimo Chiarissimo Chiarissimo Chiarissimo Chiarissimo Chiarissimo 9-11 11-13 14-16 9-11 11-13 14-16 Aula 222 333 222 222 333 222 Studente Rossi Rossi Rossi Verdi Verdi Verdi Voto 30 30 30 28 28 28 Fig. 3.16 Esempio relazione INFO_CORSO In questo semplice esempio vi è un solo corso con due studenti, ma vediamo parecchi fatti importanti che ci aspetteremmo fossero validi in qualunque relazione di questo schema. Un corso può avere luogo ogni volta a ore diverse in aule diverse. Ogni studente ha una tupla per ogni corso seguito e per ogni sessione di quel corso. Il voto per il corso è ripetuto per ogni tupla. Perciò ci aspettiamo che valga in generale la dipendenza a molti valori di Ora e Aula da Corso e si indica {Corso} àà {Ora, Aula} cioè che esista un insieme di coppie ore-aula associate ad ogni corso e non associate agli altri attributi. Adesso se consideriamo le tuple: u1 = Cs101 Chiarissimo 9-11 222 Rossi 30 u2 = Cs101 Chiarissimo 11-13 333 Verdi 28 ossia la prima e la quinta tupla della relazione in fig 3.16. Adesso, vista la dipendenza precedente, possiamo pensare di scambiare la coppia ore-aula delle tuple precedenti ed ottenere le tuple seguenti: u3 = Cs101 Chiarissimo 11-13 333 Rossi 30 u4 = Cs101 Chiarissimo 9-11 222 Verdi 28 Se controlliamo la relazione in figura 3.16 vediamo che queste tuple sono effettivamente nella relazione: rispettivamente la seconda e la quarta. La dipendenza molti valori sopra detta non vale perché le tuple si trovano nella relazione, ma essa vale perché qualunque corso c se si tiene alle ore h1 nell’aula r1 con insegnante t1 e studente s1 che ha voto g1 e se si tiene anche alle ore h2 nell’aula r2 con insegnante t2 e studente s2 che ha voto g2, allora si terrà alle ore h1 nell’aula r1 con insegnante t2 e studente s2 che ha voto g2. Esiste un algoritmo per controllare se sussistono dipendenze a molti valori tra due insiemi di attributi di una relazione, ma non ci dice come trovarle, per potere applicare regole di scomposizione (algoritmo 7.6 pag. 476 Ullman). I&T Informatica e Telecomunicazioni SpA 48 Progettazione database relazionali 3.8.2.3 Individuazione delle dipendenze Per individuare tutte le dipendenze di uno schema di relazione non è plausibile andare a vedere le tuple della relazione per dedurre le dipendenze valide. Il solo modo per determinare le dipendenze funzionali che valgono per uno schema di relazione è quello di considerare con attenzione il significato degli attributi. 3.8.3 Scomposizioni La scomposizione di uno schema di relazione R={A1, A2, … , An} consiste, nella sua sostituzione, con un insieme S={R1, R2, … , Rk} di sottoinsiemi di R tali che: R = R1 ∪ R2 ∪ … ∪ Rk Non è richiesto che i diversi Ri siano disgiunti. Il motivo per eseguire una scomposizione è che essa permette di eliminare alcuni problemi visti nel paragrafo 3.8.1. Abbiamo anche visto in tale paragrafo che gli schemi di relazioni FORNITORI e FORNISCE sono una scomposizione per lo schema di relazione INFO_FORN, e risolvono i problemi riscontrati. Ma adesso sorge un dubbio, noi ci aspettiamo che le relazioni correnti degli schemi scomposti siano la proiezione sui rispettivi attributi della relazione dello schema di partenza. Un modo per controllarlo è quello di prendere il natural join delle relazioni scomposte e vedere se riotteniamo la relazione dello schema di partenza. Se però il natural join non permette di ricostruire la relazione originale, non vi è alcun modo di ripristinarla in modo univoco. 3.8.3.1 Scomposizione lossless join (senza perdita) Se R è uno schema relazionale scomposto negli schemi R1, R2, … , Rk e D è un insieme di dipendenze, diciamo che la scomposizione possiede un lossless join (rispetto a D) o è una scomposizione lossless join (rispetto a D), se per ogni relazione r (istanza attuale) di R che soddisfa D, r è il natural join delle sue proiezioni sugli Ri. La proprietà di lossless join è necessaria se la relazione scomposta deve essere ricostruita a partire dai suoi costituenti (si esegue tra questi ultimi un natural join), di conseguenza interrogando le relazioni scomposte otteniamo gli stessi risultati della relazione originale. Facciamo un esempio di scomposizione che non è lossless join. Supponiamo di avere la relazione della figura 3.17. Impiegato Rossi Verdi Verdi Neri Neri Progetto Marte Giove Venere Saturno Venere Sede Roma Milano Milano Milano Milano Fig. 3.17 Relazione per la discussione sulla scomposizione lossless join tale relazione soddisfa le dipendenze funzionali: Impiegato à Sede Progetto à Sede I&T Informatica e Telecomunicazioni SpA 49 Progettazione database relazionali che sostanzialmente specificano il fatto che ciascun impiegato opera presso un’unica sede e che ciascun progetto è sviluppato presso un’unica sede. Si osservi che impiegato può partecipare a più progetti anche se, sulla base delle dipendenze funzionali, debbono essere tutti progetti assegnati alla sede a cui afferisce. L’idea generale delle scomposizioni è quella di scomporre la relazione di partenza sulla base delle dipendenze. Allora saremmo portati a decomporre la relazione in due parti: • Una relazione sugli attributi Impiegati e Sede, in corrispondenza alla dipendenza Impiegato à Sede. • L’altra sugli attributi Progetto e Sede, in corrispondenza alla dipendenza funzionale Progettoà Sede. L’istanza in figura 3.17 verrebbe decomposta, per mezzo di proiezioni sugli attributi coinvolti, nelle due relazioni in figura 3.18. Impiegato Rossi Verdi Neri Sede Roma Milano Milano Progetto Marte Giove Saturno Venere Sede Roma Milano Milano Milano Fig. 3.18 Relazioni ottenute per proiezione della relazione in figura 3.17 Adesso eseguiamo un natural join di queste ultime due tabelle con l’unico attributo comune, cioè Sede, ed otteniamo la relazione della figura 3.19. Impiegato Progetto Sede Rossi Verdi Marte Giove Roma Milano Verdi Saturno Milano Verdi Venere Milano Neri Giove Milano Neri Neri Saturno Venere Milano Milano Tuple spurie Fig. 3.19 Risultato del natural join tra le relazioni della fig 3.18 Osservando la relazione ottenuta notiamo che non abbiamo ricostruito tutte e sole le informazioni della relazione originaria: ad esempio l’impiegato Verdi lavora a Milano così come il progetto Saturno viene svolto presso la sede di Milano, ma in effetti Verdi non lavora a tale progetto. Abbiamo ottenuto una relazione che contiene due tuple in più, dette spurie, rispetto a quella di partenza, quindi, la scomposizione non è lossless. La definizione iniziale di scomposizione lossless join si adatta a qualunque numero di schemi relazionali. Però, per le scomposizioni in due schemi si può fornire un controllo molto più semplice dato dalla seguente definizione: I&T Informatica e Telecomunicazioni SpA 50 Progettazione database relazionali Sia r una relazione su X e siano X1 e X2 sottoinsiemi di X tali che X1 ∪ X2 = X. Inoltre, sia X0 = X1 ∩ X2. Se r soddisfa la dipendenza funzionale X0àX1 oppure la dipendenza funzionale X0à X2, allora r ha una scomposizione lossless join su X1 e X2. In modo intuitivo possiamo dire che una relazione si decompone senza perdita su due relazioni se l’insieme degli attributi comuni alle due relazioni è chiave per almeno una delle due relazioni scomposte. Nell’esempio precedente, possiamo vedere che l’intersezione degli insiemi degli attributi su cui abbiamo effettuato le due proiezioni è costituita dall’attributo Sede, che non è primo membro di alcuna dipendenza funzionale. Esiste un algoritmo che dato uno schema relazionale, un insieme di dipendenze funzionali e una scomposizione permette di dire se la scomposizione è lossless join (algoritmo 7.2 pag 448 Ullman). 3.8.3.2 Scomposizioni che conservano le dipendenze Un’altra proprietà importante di una scomposizione di uno schema di relazione è che essa mantenga le dipendenze. Diciamo che una scomposizione di uno schema di relazione conserva l’insieme delle dipendenze se l’unione di tutte le dipendenze nello schema scomposto implica logicamente tutte le dipendenze iniziali. Il motivo per cui è desiderabile che una scomposizione mantenga le dipendenze è che le dipendenze si possono considerare come vincoli di integrità (correttezza dei valori che si trovano nelle componenti delle tuple) per lo schema di relazione. Facciamo un esempio partendo dalla relazione della figura 3.17. Volendo rimuovere le anomalie, potremmo pensare, per ottenere una decomposizione lossless join, di sfruttare la dipendenza: Impiegato à Sede (potremmo procedere anche utilizzando l’altra dipendenza, Progetto à Sede) ottenendo due relazioni, una sugli attributi Impiegato e Sede e l’altra sugli attributi Impiegato e Progetto. L’istanza in figura 3.17 verrebbe così decomposta nelle relazioni in figura 3.20. Impiegato Rossi Verdi Neri Sede Roma Milano Milano Impiegato Rossi Verdi Verdi Neri Neri Progetto Marte Giove Venere Saturno Venere Fig. 3.20 Un’altra decomposizione per la relazione in figura 3.17 Il natural join delle due relazioni in figura 3.20 produce effettivamente la relazione in figura 3.17, per cui possiamo dire che la relazione in figura 3.17 ha una decomposizione lossless join su Impiegato, Sede e Impiegato, Progetto. In effetti Impiegato è chiave per la prima relazione, per cui la proprietà sopra discussa garantisce la decomposizione senza perdita. Però la decomposizione non mantiene le dipendenze funzionali. Infatti, supponiamo di voler realizzare un inserimento corrispondente all’inserimento di una tupla che specifica la partecipazione dell’impiegato Neri, che opera a Milano, al progetto Marte (svolto a Roma). Sulla relazione originaria, cioè quella in figura I&T Informatica e Telecomunicazioni SpA 51 Progettazione database relazionali 3.17, un tale aggiornamento verrebbe immediatamente individuato come illecito, perché porterebbe ad una violazione della dipendenza Progetto à Sede. Sulle relazioni decomposte, non è possibile rilevare alcune violazione di dipendenza (a meno di considerare le due relazioni contemporaneamente, ma in tal caso si verrebbero a perdere molti dei benefici della decomposizione stessa): sulle relazione avente per attributi Impiegato e Progetto non è infatti possibile definire alcuna dipendenza funzionale e quindi non ci possono essere violazioni da rilevare, mentre la tupla con i valori Neri e Milano già appartiene alla relazione su Impiegato e Sede. Possiamo quindi notare come non sia possibile effettuare alcuna verifica sulla dipendenza Progettoà Sede, perché i due attributi Progetto e Sede sono stati separati: uno in una relazione e l’altro nell’altra. In modo intuitivo possiamo dire che una decomposizione conserva le dipendenze se in ogni decomposizione, ciascuna delle dipendenze funzionali dello schema originario coinvolga attributi che compaiono tutti insieme in uno degli schemi decomposti. In questo modo, è possibile garantire, sullo schema decomposto, il soddisfacimento degli stessi vincoli il cui soddisfacimento è garantito dallo schema originario. E’ opportuno osservare che una scomposizione può possedere un lossless join rispetto ad un insieme di dipendenze F, pur non conservando F. L’esempio precedente in figura 3.20 è un esempio di tale possibilità. Inoltre una scomposizione potrebbe conservare F, pur non possedendo un lossless join. Esiste un algoritmo che dato uno schema di relazione, una scomposizione e un insieme di dipendenze funzionali permette di dire se la scomposizione conserva le dipendenze (algoritmo 7.3 pag. 454 Ullman). Una nota a sfavore delle scomposizioni è quella che aumentano i tempi di risposta delle interrogazioni sul database quindi è apprezzabile nel momento in cui sia necessario risolvere problemi come quello della ridondanza, ma non in altri casi. I&T Informatica e Telecomunicazioni SpA 52 Progettazione database relazionali 3.8.4 Prima forma normale La prima forma normale (First Normal Form – 1NF) stabilisce che in una tabella (relazione) non possono esistere colonne (attributi) definite per contenere una molteplicità di valori. Una tabella quindi non può contenere una struttura vettoriale o array, al contrario di quanto consentito in linguaggi di programmazione tradizionali. Le tabelle che contengono una colonna non rispondente a questa condizione vanno trasformate, creando per ciascuna riga della tabella di partenza tante righe quanti sono i valori multipli presenti nelle colonne della riga considerata, figura 3.21 a), oppure scomponendo in due tabelle come in figura 3.21 b). N. Protocollo Uffici interessati N. Protocollo Uffici interessati a) Trasformazione senza scomposizione Persone Rec_Num Nome Cognome Data_Nascita Figlio_1 Figlio_2 Figlio_3 Colonne ripetute Persone Rec_Num Nome Cognome Data_Nascita PK FK (colonna di join) Figli Rec_Num Nome_Figlio b) Trasformazione con scomposizione Fig. 3.21 Prima forma normale I&T Informatica e Telecomunicazioni SpA 53 Progettazione database relazionali Nelle tabelle non normalizzate viene assegnato comunque spazio di memorizzazione ai “campi ripetuti” anche se in essi non sono specificati valori. Inoltre il numero dei “campi ripetuti”, è fisso, ad esempio nella prima tabella della figura 3.21 b) per ogni persona sono ammessi al più tre figli, ma ci sono persone con quattro o più figli. In ultimo, ma non per importanza, se vogliamo ricercare un figlio nella tabella suddetta lo dobbiamo fare per tutte e tre le colonne di ogni riga. Tutti questi problemi sono stati risolti scomponendo la tabella di partenza in due tabelle in cui in una (tabella Figli) sono stati spostati le colonne ripetute. L’associazione tra le due tabelle è stabilita con la combinazione della primary key e foreign key (fig. 3.21 b)). 3.8.5 Seconda forma normale La seconda forma normale (Second Normal Form – 2NF) riguarda le tabelle in cui la chiave primaria sia composta da più attributi e stabilisce che, in questo caso, tutte le colonne corrispondenti agli attributi dipendano dall’intera chiave primaria e non da una parte di essa. Naturalmente è richiesto che la tabella sia già in 1NF. Se la tabella è dotata di chiave primaria mono attributo è già in 2NF. Nella prima parte della figura 3.22 è mostrata una tabella che non risponde a questo requisito; infatti la chiave primaria è composta da Codice_città e Codice_via; la colonna Città dipende solo da Codice_città; la colonna Via dipende invece da Codice_città e Codice_via: la colonna Città quindi non dipende da tutta la chiave, ma solo da una sua parte. Per ricondurre una tabella con questa caratteristica alla seconda forma normale è necessario scomporla in due tabelle. Nella seconda parte della figura 3.22 entrambe le tabelle, che rappresentano globalmente la stessa realtà della precedente, rispettano la seconda forma normale. Codice_città Codice_via Città Via 01 01 01 02 01 02 03 01 Roma Roma Roma Milano Verdi Bianchi Rossi Gialli Dipendenze funzionali: {Codice città} à {Città} {Codice città, Codice via} à {Via} Codice_città Codice_via Via Codice_città Città 01 01 01 02 01 02 03 01 Verdi Bianchi Rossi Gialli 01 02 03 04 Roma Milano Torino Genova Fig. 3.22 Seconda forma normale Convertendo il progetto di un database in 2NF si eliminano buona parte dei problemi visti nel paragrafo 3.8.1. I&T Informatica e Telecomunicazioni SpA 54 Progettazione database relazionali 3.8.6 Terza forma normale Delle successive forme normali diamo anche una definizione formale e per fare questo ci servono alcune definizioni. Una relazione può avere più attributi o insieme di attributi che possono formare una chiave. Con il termine chiave candidata si indica un qualsiasi insieme minimale di attributi che funzionalmente li determina tutti, mentre il termine chiave (primaria) è riservato per una particolare chiave candidata (la “principale”). Con il termine superchiave si indica un qualunque superinsieme (è una chiave o contiene una chiave) di una chiave. Si definisce primario un attributo A in una relazione R se A è membro di una qualunque chiave di R. Se A non e membro di alcuna chiave, allora A è non primario. Uno schema di relazione R è in terza forma normale (Third Normal Form - 3NF) se ogni volta che in R vale X à A e A non è in X, allora X è una superchiave per R, oppure A è primario, cioè la 3NF stabilisce che non esistono dipendenze tra colonne di una tabella se non basate sulla chiave primaria, o se esistono, l’attributo determinato è primario. Naturalmente è richiesto che la tabella sia già in 2NF. Nella prima parte della figura 3.23 sono mostrate due tabelle che non rispondono a questo requisito: le dipendenze funzionali individuate per la prima tabella sono: {N_Protocollo} à {Mittente, Tipo} {Tipo} à {Urgenza} per la seconda: {Tipo} à {Descrizione} la violazione è data dal fatto che nella prima tabella la chiave primaria è N_Protocollo; la colonna Urgenza non dipende da N_Protocollo, bensì, dalla chiave primaria della seconda tabella, ovvero Tipo. Quindi la dipendenza funzionale: {Tipo} à {Urgenza} viola la 3NF in quanto Tipo non è superchiave per la prima tabella e Urgenza non è primario. Anche in questo caso la dipendenza va ricondotta alla tabella opportuna, creandone eventualmente una ad hoc. Nel nostro esempio le modifiche da apportare allo schema logico rappresentato sono le seguenti: 1) eliminare la colonna urgenza dalla prima tabella, 2) aggiungere la colonna Urgenza alla seconda tabella, ottenere così la terza tabella della figura 3.23. I&T Informatica e Telecomunicazioni SpA 55 Progettazione database relazionali Tipo 1 2 3 N_Protocollo Mittente Tipo Urgenza 1 2 3 4 5 001 002 003 002 003 1 2 1 2 3 Si No Si No Si Descrizione Lettera Memo Telegramma Tipo Descrizione Urgenza 1 2 3 Lettera Memo Telegramma Si No Si Fig. 3.23 Terza forma normale (anche BCNF) Si scompone in modo che a ciascuna dipendenza corrisponde una diversa relazione la cui chiave è proprio il primo membro della dipendenza stessa. In tale modo, il soddisfacimento della 3NF è garantito, per la definizione stessa della 3NF. Nell’esempio precedente, la separazione delle dipendenze (e quindi dei concetti da essa rappresentati) è stata facilitata dalla struttura delle dipendenze stesse, “naturalmente” separate e indipendenti l’una dall’altra. In effetti in molti casi pratici, la decomposizione può essere effettuata producendo tante relazioni quante sono le dipendenze funzionali definite (o meglio, le dipendenze funzionali con diverso primo membro). In generale, purtroppo, le dipendenze possono avere una struttura complessa: può non essere necessario (possibile) basare la decomposizione su tutte le dipendenze e può essere difficile individuare quelle su cui si deve basare la decomposizione. Vediamo un esempio semplicissimo, esaminando il quale capiamo subito quale sarebbe la natura della decomposizione, ma che, al tempo stesso, ci permette di individuare il problema. Consideriamo la relazione della figura 3.24. Impiegato Neri Verdi Rossi Mori Bianchi Categoria 3 3 4 4 5 Stipendio 30 30 50 50 72 Fig. 3.24 Una relazione con varie dipendenze funzionali I&T Informatica e Telecomunicazioni SpA 56 Progettazione database relazionali Notiamo che soddisfa la dipendenza: {Impiegato, Categoria} à {Stipendio} ma anche le dipendenze: {Impiegato} à {Categoria} {Categoria} à {Stipendio} Procedendo come in precedenza, potremmo facilmente ottenere una base di dati con due relazioni entrambe in 3NF. D’altra parte, per la stessa relazione, avremmo potuto individuare, insieme alla dipendenza funzionale: {Categoria} à {Stipendio} anche la dipendenza: {Impiegato} à {Categoria, Stipendio} anziché {Impiegato} à {Categoria}, che avrebbe descritto il frammento di realtà con la stessa accuratezza (o quasi). In questo secondo caso, non avremmo avuto strumenti per generare una naturale decomposizione in 3NF, perché ovviamente la dipendenza {Impiegato} à {Categoria, Stipendio} ricopre tutti attributi e quindi non suggerisce alcuna relazione decomposta. Da notare come in un esempio così semplice l’individuazione delle dipendenze possa produrre difficoltà nella decomposizione; si può immaginare che cosa possa succedere quando la relazione è complessa e su di essa sono definite diverse dipendenze funzionali, fra loro interconnesse. In tal caso non si può fare a meno di trattare la normalizzazione in modo formale che però esula dagli scopi di questo documento. 3.8.7 Linee guida sulla normalizzazione 1) Partire dalle tabelle non normalizzate 2) Individuare le chiavi primarie, ed eventuali altre dipendenze funzionali. 3) Individuare e risolvere le violazioni della 1NF rimuovendo tutti gli attributi ripetuti. • Se esistono attributi ripetuti trasformare la tabella in questione creando per ciascuna riga della tabella di partenza tante righe quanti sono i valori multipli presenti nelle colonne della riga considerata oppure spostando le colonne ripetute in un’altra tabella dove la chiave primaria della prima tabella diventa chiave esterna in quest’ultima (fig 3.21 a) e b)). 4) Individuare e risolvere le violazioni della 2NF assicurando che ciascun attributo dipenda dall’intera chiave. • Se alcuni attributi non dipendono dall’intera chiave (dipendenze funzionali in cui il termine a sinistra non è l’intera chiave) creare una nuova tabella con gli altri attributi che dipendono da parte di questa. • Definire in questa nuova tabella la chiave primaria coincidente con la parte determinante della chiave originale. • Eliminare dalla tabella originale gli attributi (non chiave) spostati nella nuova tabella (fig. 3.22). 5) Individuare e risolvere le violazioni della 3NF assicurando che non esistano attributi non chiave che dipendano da altri attributi non chiave. • Se esiste un tale attributo, rimuoverlo dalla tabella originale insieme da tutti gli altri che dipendono dallo stesso determinante (dipendenze funzionali tra attributi non chiave), e creare una nuova tabella che li contenga. I&T Informatica e Telecomunicazioni SpA 57 Progettazione database relazionali • Gli attributi determinanti diventano chiave primaria nella nuova tabella e permangono nella precedente tabella in qualità di chiavi esterne. • (Eliminare gli attributi che sono dipendenti dai determinanti dalla tabella di partenza (fig. 3.23)). Il processo precedente permette di verificare la qualità delle relazioni, a volte non occorre fare nessuna trasformazione, perché lo schema del database si trova gia in 3NF, in questo contesto, la teoria della normalizzazione costituisce un utile strumento di analisi della qualità di un progetto. Il motivo per cui a volte non necessita fare alcuna trasformazione sullo schema del database è perché la metodologia di progettazione (concettuale, logica) porta a schemi di database già in 3NF, tramite l’individuazione e la separazione dei concetti fondamentali della realtà da modellare creando entità e/o associazioni distinte. Per la maggior parte delle situazioni quando un progetto di schema di database si trova in terza forma normale è più che ottimo. Nei successivi paragrafi, per completezza, illustreremo la forma normale di Boyce-Codd e brevemente, la quarta forma normale (nella pratica poco usata). 3.8.8 Forma normale di Boyce-Codd La forma normale di Boyce-Codd è una condizione molto forte, nel senso che non è sempre possibile portare in questa forma uno schema relazionale tramite scomposizione, senza perdere la capacità di mantenere le dipendenze. Mentre la terza forma normale fornisce la maggior parte dei vantaggi della forma normale di Boyce-Codd, per quanto riguarda l’eliminazione delle anomalie, però è una condizione che possiamo raggiungere per uno schema arbitrario di database, senza perdere la conservazione delle dipendenze o la proprietà di lossless-join. Uno schema di relazione R con dipendenze F, si dice essere in forma normale Boyce-Codd (BoyceCodd Normal Form – BCNF) se ogni volta in R vale XàA, e A non è in X, allora X è una superchiave di R, cioè X è una chiave o contiene una chiave. Ovvero, la BCNF stabilisce che non esistono dipendenze tra attributi di una relazione se non basate sulla chiave primaria. Si consideri lo schema relazionale (CITTA’, VIA, CAP), abbreviato con CSZ, con le dipendenze CSà Z e ZàC. Si può dimostrare che le chiavi di questo schema relazionale sono CS e SZ. Lo schema CSZ con queste dipendenze non si trova in BCNF, dato che in CSZ vale ZàC, però Z non è una chiave di CSZ e neppure contiene una chiave. La scomposizione però in 3NF poiché C è primario e CS è chiave. L’esempio della figura 3.23 è in BCNF. La ragione che sta alla base della BCNF è quella di eliminare le ridondanze che possono essere introdotte dalle dipendenze funzionali e non eliminate dalle precedenti forme normali. In tale forma normale, facendo uso solo delle dipendenze funzionali, non è possibile prevedere nessun valore dati gli altri. I&T Informatica e Telecomunicazioni SpA 58 Progettazione database relazionali 3.8.8.1 Osservazioni sulla 3NF e BCNF Naturalmente dato che la 3NF è più debole della BCNF, non può eliminare tutte le ridondanze. L’esempio canonico è quello CSZ precedente, che è in 3NF e si possono avere coppie di tuple come in figura 3.25: Città (C) c ? Via (S) s1 s2 CAP (Z) z z Fig. 3.25 Ridondanza in 3NF in cui dalla dipendenza Zà C possiamo dedurre che il valore incognito è c. Si osservi che queste tuple non possono violare l’altra dipendenza CSàZ perché altrimenti sarebbero la stessa tupla. Le due più importanti proprietà per schemi di database sono il lossless join e la conservazione delle dipendenze e sono viste come un tutt’uno. I risultati a cui si è giunti sono che per qualunque schema relazionale vi è una scomposizione lossless join in forma normale Boyce-Codd e una in terza forma normale che ha un lossless join e conserva anche le dipendenze. Tuttavia può non esserci una scomposizione di uno schema relazionale in forma normale Boyce-Codd che conservi le dipendenze. Si può quindi affermare che, talvolta, la forma normale di Boyce-Codd non è raggiungibile. Esiste un algoritmo che dato uno schema relazionale e un insieme di dipendenze funzionali trova una scomposizione lossless join per la BCNF (algoritmo 7.4 pag. 461 Ullman). Esiste un algoritmo che dato uno schema relazionale e un insieme di dipendenze funzionali trova una scomposizione lossless join che conserva le dipendenze per la 3NF (algoritmo 7.5 e teorema 7.8 pagg. 465-466 Ullman). 3.8.8.2 Analisi non accurata Spesso la non raggiungibilità della BCNF di uno schema di database può essere dovuta ad una analisi non sufficientemente accurata dell’applicazione. Facciamo un esempio. Consideriamo la relazione in figura 3.26. Funzionario Rossi Verdi Verdi Neri Neri Progetto Marte Giove Marte Saturno Venere Sede Roma Milano Milano Milano Milano Fig. 3.26 Una relazione con decomposizione problematica Su tale relazione possiamo supporre che siano definite le seguenti dipendenze: • {Funzionario} à {Sede}: ogni funzionario opera presso una sede; • {Progetto, Sede} à {Funzionario}: ogni progetto ha più responsabili, ma in sedi diverse, e ogni funzionario può essere responsabile di più progetti, però, per ogni sede, un progetto ha un solo responsabile. I&T Informatica e Telecomunicazioni SpA 59 Progettazione database relazionali La relazione non è in BCNF, perché il primo membro della dipendenza {Funzionario}à {Sede} non è superchiave. Al tempo stesso, possiamo notare come non sia possibile alcuna buona decomposizione di questa relazione; infatti, la dipendenza {Progetto, Sede} à {Funzionario} coinvolge tutti gli attributi e quindi nessuna decomposizione è in grado di conservarla. Se però esaminiamo meglio le specifiche, possiamo arrivare alla conclusione che avremmo potuto descrivere il frammento di realtà di interesse in maniera più appropriata introducendo un ulteriore attributo Reparto, che partiziona (sulla base dei responsabili) le singole sedi, vedi figura 3.27. Funzionario Rossi Verdi Verdi Neri Neri Progetto Marte Giove Marte Saturno Venere Sede Roma Milano Milano Milano Milano Reparto 1 1 1 2 2 Fig. 3.27 Modifica della relazione in figura 3.26 Le dipendenze possono, in questo caso, essere così definite: • {Funzionario}à{Sede, Reparto}: ogni funzionario opera presso una sede e dirige un reparto; • {Sede, Reparto}à{Funzionario}: per ogni sede e reparto c’è un solo funzionario; • {Progetto, Sede}à{Reparto}: per ogni sede, un progetto è assegnato ad un solo reparto (e, di conseguenza, ha un solo responsabile); la dipendenza funzionale {Progetto, Sede}à {Funzionario} è quindi ricostruibile. Per questo schema, esiste una buona decomposizione, come mostrato dall’istanza in figura 3.28. Funzionario Sede Rossi Roma Neri Milano Verdi Milano Reparto 1 2 1 Progetto Marte Giove Marte Saturno Venere Sede Roma Milano Milano Milano Milano Reparto 1 2 2 1 1 Fig. 3.28 Una buona decomposizione della relazione in figura 3.27 • la decomposizione è senza perdita, perché gli attributi comuni Sede e Reparto formano una chiave per la prima relazione; • le dipendenze sono conservate, perché per ciascuna dipendenza esiste una relazione decomposta che ne contiene tutti gli attributi; • entrambe le relazioni sono in BCNF, perché tutte le dipendenze hanno il primo membro costituito da una chiave. I&T Informatica e Telecomunicazioni SpA 60 Progettazione database relazionali 3.8.9 Quarta forma normale Esiste una generalizzazione della forma normale di Boyce-Codd, che si applica a schemi di relazione con dipendenze a molti valori, e che permette di eliminare le ridondanze provocate da queste dipendenze e non eliminate dalle precedenti forme normali. La definizione formale è data di seguito. Sia R uno schema di relazione e D l’insieme di dipendenze applicabili a R. Diciamo che R è in quarta forma normale (Fourth Normal Form – 4NF) se ogni volta che nella chiusura di D esiste una dipendenza a molti valori Xàà Y, dove Y non è sottoinsieme di X e X∪ Y non contiene tutti gli attributi di R, si verifica che X sia superchiave di R. Notiamo che il significato di una superchiave (chiave) è quello di un insieme di attributi che determina funzionalmente R. Mentre la chiusura di un insieme di dipendenze F, è l’insieme delle dipendenze funzionali logicamente implicato da F. Si osservi che se R è in quarta forma normale, allora è anche in forma normale di Boyce-Codd, cioè la condizione di quarta forma normale è più forte della forma normale di Boyce–Codd. La 4NF possiede una scomposizione lossless join rispetto ad un insieme di dipendenze D (pag. 478 Ullman). 3.9 Implementazione dello schema logico Ricapitolando, il corretto progetto di una base di dati relazionale dovrebbe partire dalla definizione dello schema derivato dall’esame della realtà di interesse, per arrivare alla definizione di uno schema logico relazionale normalizzato. Esistono strumenti informatici detti CASE (Computer Aided Software Engineering) che aiutano l’analista in questo processo; esempio di questa classe di strumenti è Bachman della Cayenne Software Inc. Lo schema relazionale deve essere tradotto utilizzando un RDBMS (Relational Database Management System); tra i più diffusi troviamo Oracle, Informix, DB2 e Microsoft Access. Un RDBMS, tramite il suo DDL, permette di implementare lo schema logico attraverso la creazione di tabelle, chiavi primarie e esterne, indici, viste e così via, fa rispettare i vincoli di tupla, di dominio, di unicità, di Not Null, di integrità referenziale, ecc. Nella pratica, nella progettazione dello schema logico, per ragioni di efficienza si deve compiere spesso un ulteriore passo detto di denormalizzazione in cui, in parziale contrasto con la teoria relazionale, si ammette una certa ridondanza dei dati in cambio di migliori prestazioni del sistema in termini di tempi di risposta. I&T Informatica e Telecomunicazioni SpA 61 Progettazione database relazionali 4 Progettazione fisica La progettazione fisica permette la rappresentazione dello schema logico per mezzo di strutture fisiche di memorizzazione. Ad, esempio una relazione può essere realizzata fisicamente per mezzo di un file sequenziale, o di un file hashed o di file sequenziale con uno o più indici. Ogni tupla della relazione viene memorizzata come un record fisico nella struttura dati scelta, e ogni componente della tupla è memorizzata in un campo del record fisico. In questo capitolo vediamo le più comuni (e semplici) strutture fisiche di memorizzazione, e alcune semplici strategie di progettazione fisica. 4.1 Strutture fisiche di accesso Le strutture fisiche di accesso descrivono il modo in cui vengono organizzati i dati per garantire operazioni di ricerca e di modifica efficienti da parte dei programmi applicativi. In genere, ciascun DBMS ha a disposizione un numero abbastanza limitato di tipi di strutture di accesso; ad esempio, nei sistemi relazionali sono disponibili semplici indici, che vengono definiti dal progettista tramite istruzioni DDL. In questo paragrafo considereremo strutture sequenziali, ad accesso calcolato e ad albero (B-tree). 4.1.1 Strutture sequenziali Le strutture sequenziali sono caratterizzate da una disposizione sequenziale delle tuple in memoria di massa; il file è costituito da vari blocchi di memoria consecutivi, e le tuple vengono inserite nei blocchi rispettando una sequenza. Tale sequenza può essere di vari tipi: • In una organizzazione entry-sequenced, la sequenza delle tuple è indotta dal loro ordine di immissione. • In una organizzazione ISAM, la sequenza delle tuple dipende dal valore assunto in ciascuna tupla da un campo di ordinamento. 4.1.1.1 Struttura sequenziale entry-sequenced (file sequenziale) Una struttura sequenziale entry-sequenced è ottimale per svolgere operazioni di lettura e scrittura sequenziali. Dato che le tuple non sono disposte con un ordine prestabilito, il modo tipico di accedere al loro contenuto è tramite scansione (scan) sequenziale. D’altra parte questa organizzazione usa tutti i blocchi a disposizione del file e tutti gli spazi all’interno dei blocchi e, quindi, la scansione risulta particolarmente efficiente. E’ anche possibile accedere ad una tupla specifica, nel caso di tuple a lunghezza fissa, pur di conoscere in che ordine essa è stata inserita. Per quanto riguarda le operazioni di caricamento iniziale dei dati e di inserimento, esse avvengono alla fine del file ed in modo sequenziale; è sufficiente gestire un puntatore all’ultima tupla per poter eseguire l’operazione. Il principale problema è posto dalle operazioni di modifica e cancellazione: poiché le tuple vengono disposte in sequenza, ogni modifica che comporti un aumento delle dimensioni della tupla non può essere facilmente gestita “in loco”, ed ogni cancellazione causa un potenziale spreco di memoria, in quanto viene implementata spesso lasciando inutilizzato dello spazio. 4.1.1.2 Struttura sequenziale ISAM (file indicizzato) L’organizzazione ISAM dei file (Indexed Sequential Access Method, metodo di accesso sequenziale con indici) assegna a ciascuna tupla una posizione in base al valore del campo chiave. Questa organizzazione è basata sull’idea di dare alle tuple un ordinamento fisico che rifletta l’ordinamento I&T Informatica e Telecomunicazioni SpA 62 Progettazione database relazionali lessicografico dei valori presenti in un campo chiave. In realtà non è necessario che il campo scelto per definire l’ordinamento delle tuple sia un campo chiave, anche se in questo paragrafo supporremo di ordinare i record in base al valore delle loro chiavi che, inoltre, individueranno in maniera univoca un record. Per quanto riguarda i criteri di ordinamento, gli usuali domini di valori, come le stringhe di caratteri, gli interi o i reali, seguono un ordinamento convenzionale: per i numeri interi o reali si considera quello numerico, mentre per le stringhe di caratteri abbiamo l’ordine lessicografico (o dictionary). Per aumentare la velocità di accesso al file ordinato (che chiamiamo file principale), si definisce un secondo file (chiamato sparse index, indice rado), che consiste nelle coppie: (<valore chiave>,<indirizzo del blocco>) Per ogni blocco del file principale, nel file indice esiste un record (µ,b): µ è un valore non superiore (≤) a quello di tutte le chiavi contenute nel blocco b e maggiore (>) dei valori delle chiavi di ogni blocco che precede b. Il primo campo di (µ, b) è una chiave e il file indice è ordinato rispetto ad essa. Se vogliamo trovare il blocco b del file principale che contiene un record con chiave µ dobbiamo ricercare nel file indice il record: tale che µj ≤µ (µ ≥ µj) (µj, b) dove il record successivo: (µk, bk) è tale che µ < µk in questa situazione si dice che µk copre µ. File principale bi File indice (µi,bi) b (µj,b) (µk,bk) bk µi1 … altri campi … µi2 … … … … µin … … µj1 … … µj2 … … … … µ … … … µjn … … µk1 … … µk2 … … … … µkn … … µj≤µjp µj>µip p=1,… ,n p=1,… ,n (angolo superiore sinistro blocco) Fig. 4.1 File indice e file principale I&T Informatica e Telecomunicazioni SpA 63 Progettazione database relazionali 4.1.1.2.1 Ricerca in un indice La strategia più semplice consiste sicuramente nell’usare una tecnica di ricerca lineare (cioè scandire l’indice dall’inizio controllando ogni record fino a trovare l’indice che copre µ). Questo metodo non è conveniente se non per gli indici più piccoli, dato che in tal caso si può richiamare in memoria principale l’intero indice e, in media per eseguire una ricerca con successo, si accederà a metà dei blocchi. Comunque fare una ricerca lineare sull’indice è meglio che farla sul file principale; se questo possiede R record per blocco, allora i record dell’indice sono 1/R rispetto a quelli del file principale. Inoltre di solito i record indice sono più corti e possono così essere raggruppati in un numero maggiore per blocco. Un metodo migliore è rappresentato dall’effettuare una ricerca binaria sulle chiavi del file indice. Si supponga che B1,… ,Bn siano i blocchi che contengono il file indice (non il file principale) e siano rispettivamente µ1,… µn le prime chiavi di ognuno di tali blocchi. Per trovare il blocco che contiene il record del file principale con chiave µ, dovremo prima analizzare il blocco indice B[n/2] e confrontare µ con µn/2. Se µ<µn/2, dovremo iterare il processo sui blocchi B1,… ,B[n/2]-1, altrimenti considerare i blocchi Bn/2,… ,Bn. Alla fine rimarrà un solo blocco, in cui potremo effettuare una ricerca lineare per trovare nell’indice il valore chiave che copre µ. Un metodo ancora più efficiente è noto come ricerca per interpolazione o per calcolo degli indirizzi. Esso si basa sulla nostra conoscenza della statistica della distribuzione attesa per i valori della chiave e sull’affidabilità di tale distribuzione. Se ad esempio ci si chiede di cercare Giuseppe Rossi sulla guida telefonica, non la apriamo a metà, ma a circa il 75%, “sapendo” che è pressappoco il punto in cui si trova la R. Se ci trovassimo alla S, torniamo circa il 5%, e non a metà dall’inizio, come faremmo invece col secondo passo in una ricerca binaria. In generale, si supponga di avere un algoritmo che, dato il valore chiave µ1, fornisca il valore della frazione tra altre due chiavi µ2, µ3 in cui ci aspettiamo che si trovi µ1. Chiamiamo questa funzione f(µ1,µ2,µ3). Siano B1,… ,Bn i blocchi in cui si trova l’indice (o parte di esso) ed indichiamo µ2 la prima chiave di B1 e µ3 l’ultima di Bn. Sia i un indice tale che i = [nf(µ1,µ2,µ3)], allora analizzeremo il blocco Bi per definire quale rapporto vi sia tra la prima chiave di tale blocco e µ1. Come in una ricerca binaria, tale processo verrà iterato su B1,… Bi-1 o su Bi,… Bn (sull’insieme di blocchi che contiene la chiave che copre µ1) fino a che non rimarrà un solo blocco. 4.1.2 Strutture con accesso calcolato (file hashed) Una struttura con accesso calcolato garantisce, al pari dell’organizzazione ISAM, un accesso associativo ai dati, in cui, cioè, la locazione fisica dei dati dipende dal valore assunto da un campo particolare ma è preferibile ad essa perché le tuple non devono essere disposte in ordine in memoria di massa. L’idea che sta alla base dell’organizzazione hashed dei file è quella della suddivisione del file in buckets, a seconda del valore della chiave. Per ogni file memorizzato in tal modo, esiste una funzione hash h che prende come argomento un valore della chiave e fornisce un intero tra 0 e B-1, dove B è il numero dei bucket usati per tale file. L’intero h(v) è il numero di bucket in corrispondenza del valore chiave v. Ogni baucket è composto da un numero (possibilmente piccolo) di blocchi e questi sono organizzati come raggruppamento. Vi è un array di puntatori, con indice tra 0 e B-1, che chiamiamo indice del bucket. In esso l’elemento i è un puntatore al primo blocco: tale puntatore viene detto testata del bucket. Nel bucket i tutti i blocchi sono collegati in una lista tramite puntatori e, nell’ultimo della lista (o nella testata del bucket, se questo è attualmente vuoto) vi è un puntatore nullo. È normale I&T Informatica e Telecomunicazioni SpA 64 Progettazione database relazionali che B sia abbastanza piccolo da permettere che l’intero indice del bucket risieda in memoria principale, mentre se così non fosse, l’indice si estenderebbe su tutti i blocchi necessari ed ognuno di questi verrebbe richiamato in memoria quando necessario. 4.1.2.1 Funzioni hash Esistono molti tipi di funzioni utilizzabili come funzioni hash h. È fondamentale che l’intervallo sia 0,… ,B-1 ed è opportuno che h ripartisca le chiavi: ossia che al variare di v su tutti i possibili valori della chiave, h(v) assuma in modo quasi equiprobabile tutti i possibili valori. Un semplice esempio di funzione hash è quello che trasforma ogni chiave in un intero e poi ne prende il resto modulo B. Se iniziamo con valori interi per la chiave, calcoliamo semplicemente h(v) = v mod B. Un esempio di file hashed che usa la funzione hash precedente con B=4 è mostrato in figura 4.2. Bucket Blocchi 0 o 1°Rec 1 17 2 2 3 23 5°Rec 13 5 29 o o 7 35 19 11 31 o Directory dei Bucket (indice) Fig. 4.2 Organizzazione di un file hashed 4.1.3 Strutture ad albero (B-tree) Le strutture ad albero, denominate B-tree o B+-tree, sono le più frequentemente usate nei DBMS di tipo relazionale. Esse consentono accessi associativi, cioè in base ad un valore di un attributo chiave (key), senza essere necessariamente vincolare la collocazione fisica delle tuple in posizioni specifiche del file. In genere, quando un utente specifica a livello di DDL la definizione di un indice relativo ad un attributo o una lista di attributi di una tabella, ciò corrisponde a definire opportune strutture ad albero. Come sempre, ogni albero è caratterizzato da un nodo radice, vari nodi intermedi e vari nodi foglia; ogni nodo corrisponde ad un blocco. I legami tra nodi vengono stabiliti da puntatori; in genere, ogni nodo ha un numero di discendenti abbastanza grande (non è raro il caso in cui ogni nodo ha decine o centinaia di successori); questo consente di costruire alberi con un numero limitato di livelli. Un altro requisito importante è che la lunghezza di un cammino che collega il nodo radice da un qualunque nodo foglia sia costante (B-tree, alberi bilanciati). In tal caso, i tempi di accesso alle informazioni contenute nell’albero sono praticamente costanti. L’organizzazione fisica avviene tramite indici (file), e siccome gli indici non sono altro che file con record non puntati, non vi è motivo per cui non si possa avere un indice di un indice, un indice di quest’ultimo e così via, fino a quando si arriva a un livello di indice che sia contenuto in un solo blocco, come suggerito dalla figura 4.3. I&T Informatica e Telecomunicazioni SpA 65 Progettazione database relazionali Indice di 3°livello Nodo (blocco) radice Indice di 2°livello Indice di 1°livello File principale Blocchi del file principale Fig. 4.3 Un indice a molti livelli e interpretazione a struttura di albero Di fatto una tale struttura potrebbe essere molto più efficiente rispetto a un file con un unico livello di indice. Nella struttura della figura 4.3 il file principale è ordinato per valore di chiave. Il primo livello di indice consiste delle coppie (v, b) in cui b è un puntatore al blocco B del file principale e v è la prima chiave nel blocco B. Naturalmente anche l’indice è ordinato per valore di chiave. Il secondo livello di indice possiede coppie (v, b), in cui b punta al blocco indice di primo livello e v ne è la prima chiave e così via. La differenza tra un B-tree e un B+-tree è che negli alberi B+, i nodi foglia sono collegati da una catena in base all’ordine imposto dalla chiave. Tale catena consente di svolgere in modo efficiente anche interrogazioni il cui predicato di selezione definisce un intervallo di valori ammissibili. In particolare questa struttura dati consente anche una scansione ordinata in base ai valori di chiave dell’intero file, che risulta abbastanza efficiente. Negli altri alberi (B-tree) non viene previsto di collegare sequenzialmente i nodi foglia. 4.2 Progettazione fisica di una base di dati Nell’ambito del progetto di una base di dati, la fase finale è costituita dalla progettazione fisica, che, ricevendo in ingresso lo schema logico del DB e le caratteristiche del sistema scelto, produce in uscita lo schema fisico del database, costituito dalle effettive definizioni delle relazioni e soprattutto delle strutture fisiche utilizzate, con i relativi parametri. L’attività di progettazione fisica di una base di dati relazionale può essere molto complessa, perché oltre alle scelte relative alle strutture fisiche può essere necessario definire molti parametri, che vanno dalle dimensioni iniziali dei file alle possibilità di espansione, dalla contiguità di allocazione alla quantità e alle dimensioni delle aree di transito per scambio di informazioni tra memoria principale e secondaria. La maggior parte delle scelte da effettuare nel corso della progettazione fisica dipende in effetti dallo specifico sistema di gestione utilizzato, e quindi risulta difficile fornire una panoramica completa. Indicheremo solo le linee principali, che possono però essere considerate sufficienti in presenza di basi di dati di dimensioni non enormi o con carichi di lavoro non particolarmente complessi. I&T Informatica e Telecomunicazioni SpA 66 Progettazione database relazionali Assumiamo che il DBMS a nostra disposizione preveda solo file non ordinati, con possibilità di definizione di indici. In questo contesto, ignorando gli altri parametri, la progettazione fisica può essere ricondotta ad una attività di individuazione degli indici da definire su ciascuna relazione (a parte l’attività semplice di specifica degli schemi delle relazioni nello specifico DDL del sistema usato, con i tipi di dati ammessi per i vari attributi). Per orientarci nella scelta degli indici, è opportuno ricordare che le operazioni più delicate in un DB relazionale sono quelle di selezione (che corrisponde all’accesso ad uno o più record sulla base dei valori di uno o più attributi) e di join (che richiede di combinare ennuple di relazioni diverse sulla base dei valori di uno o più attributi di ciascuna di tali relazioni). Ciascuna delle due operazioni può essere eseguita in maniera più efficiente se sui campi interessati è definito un indice, che permette un accesso diretto. Consideriamo, ad esempio, un DB su due relazioni, la prima, IMPIEGATI, sugli attributi Matricola (che costituisce la chiave), Cognome, Nome e Dipartimento (che indica il codice del dipartimento di afferenza) e la seconda, DIPARTIMENTI, sugli attributi Codice (che costituisce la chiave), Nome e Direttore. Volendo effettuare sulla relazione IMPIEGATI una selezione sull’attributo Matricola (ricerca di un impiegato dato il numero di matricola), se sulla relazione è presente un indice su tale attributo si può procedere con un accesso diretto, molto efficiente, altrimenti si deve effettuare un accesso sequenziale, con un costo proporzionale alla dimensione del file. Lo stesso vale per una ricerca basata sul cognome dell’impiegato; vale la pena notare che se è definito un indice su un attributo, solo le ricerche basate su tale attributo possono trarne beneficio: se la relazione ha un indice su Matricola e non ha un indice su Cognome, le selezioni su Matricola potranno essere eseguite in modo efficiente mentre quelle su Cognome rimarranno inefficienti. Un equi-join fra le due relazioni volto a collegare ciascun impiegato con il corrispondente dipartimento, in presenza di un indice sulla chiave Codice della relazione Dipartimenti, può essere effettuato in modo molto efficiente tramite il metodo dei nested-loop; si scandisce sequenzialmente la relazione IMPIEGATI (e questo non è un problema, perché tutte le sue ennuple contribuiscono al risultato) e, per ciascuna di esse, si effettua un accesso diretto alla relazione DIPARTIMENTI sulla base dell’indice. Se l’indice non è definito, l’accesso alla relazione DIPARTIMENTI risulta inefficiente, e tutto il join risulta più costoso. E’ importante ricordare come molti dei join che si presentano nelle applicazioni sono equi-join e per almeno una delle due relazioni i campi coinvolti formano una chiave, come nell’esempio appena mostrato. Al tempo stesso possiamo notare come quasi sempre la chiave di una relazione sia coinvolta in operazioni di selezione o di join (o entrambe). Pertanto possiamo dire che è ragionevole definire, su ciascuna relazione, un indice in corrispondenza della relativa chiave (indice primario). Tali indici solitamente vengono creati in automatico dal DBMS. Inoltre possono essere definiti indici (indici secondari) su altri campi su cui vengono effettuate operazioni di selezione oppure su cui è richiesto un ordinamento in uscita (perché un indice ordina logicamente i record di un file, rendendo nullo il costo di un ordinamento). Queste osservazioni costituiscono la base di una semplice strategia di progettazione fisica. Definiti in questo modo gli indici, si può sperimentare sul campo il comportamento della nostra applicazione: se le prestazioni risultano insoddisfacenti, si possono aggiungere altri indici, procedendo però con grande attenzione, in quanto l’aggiunta di un indice comporta un aggravio del carico per far fronte alle operazioni di modifica. Talvolta, inoltre, il comportamento del sistema è imprevedibile, e l’aggiunta di indici non altera la strategia di ottimizzazione delle interrogazioni principali, risultando del tutto inefficace. É buona norma, dopo l’aggiunta di un indice, verificare che le interrogazioni ne facciano effettivamente uso. Per questo motivo, l’attività di scelta degli indici nell’ambito del progetto fisico delle basi di dati relazionali è svolta spesso in modo empirico, con un approccio per tentativi; più in generale, l’attività di regolazione (tuning) del progetto fisico consente spesso di migliorare le prestazioni della base di dati. I&T Informatica e Telecomunicazioni SpA 67 Progettazione database relazionali Appendici I&T Informatica e Telecomunicazioni SpA 68 Progettazione database relazionali Appendice A - Data Flow Diagram I data flow diagram (Diagrammi di Flusso Dati - DFD) modellano (specificano) le funzioni svolte da un sistema informativo. Hanno una attraente notazione grafica che li rende facili da usare: Simbolo di funzione (processo) Simbolo di dispositivo di input Simbolo di dispositivo di output Simbolo di flusso dati Simbolo di memorizzazione dati (file, database, ecc.) L’idea alla base della costruzione di un DFD che modella una particolare realtà è quella di vedere la realtà da modellare come un macroprocesso, e a livelli successivi esplodere questo macroprocesso in sottoprocessi che rappresentano situazioni sempre più in dettaglio. I processi si scompongono fintanto che non si arriva a un processo che non è più scomponibile in altri processi (processo elementare) che viene a questo punto descritto in uno pseudolinguaggio o in linguaggio naturale. Supponiamo per esempio di voler rappresentare il frammento di realtà che esprime la gestione di un ordine nel nostro sistema informativo del mobilificio. L’esempio che segue è molto semplificato ma rende l’idea di come si costruisce un DFD. Si parte sempre da un DFD di livello 0 nel quale sono rappresentate le entità esterne che partecipano al processo (fig A.1). NEGOZIO Ordine GESTIONE ORDINE 0 Spedizione NEGOZIO Fig. A.1 DFD-0 Entità esterne che partecipano al processo GESTIONE ORDINI I&T Informatica e Telecomunicazioni SpA 69 Progettazione database relazionali Le entità esterne sono i NEGOZI, il processo che vogliamo gestire è GESTIONE ORDINI. Esplodiamo quest’ultimo processo nei sottoprocessi della figura A.2. Ordine CONVALIDA ORDINE 1 Ordine convalidato DB Mobili (tbl Ordine) Ordine EVASIONE ORDINE 2 Spedizione Fig. A.2 DFD-1 Gestione ordine Esplodiamo adesso il processo Convalida Ordine come in figura A.3. Ordine Controllo Codice articoli 1 Articolo non esistente Rispedisci Negozio 3 Chk Codice Prodotto esistente Qta non disponibile Ordine rifiutato Controllo Quantità 2 D B Chk Quantità Qta disponibile (ordine convalidato) Memorizza Ordine 4 Negozio M O B I L I Ordine Fig. A.3 DFD-1.1 Convalida Ordine I&T Informatica e Telecomunicazioni SpA 70 Progettazione database relazionali I processi ottenuti sono elementari, la loro funzione va espressa in pseudolinguaggio o linguaggi naturale. Ci rimane da esplodere il processo Evasione Ordine così come fatto in figura A.4. Composizione Ordine 1 Articoli Richiesti -Dati ordine -Dati articoli Dati negozio Documentaz Spedizione 2 D B M O B I L I Spedizione Negozio Fig. A.4 DFD-1.2 Evasione Ordine I processi ottenuti sono elementari. L’insieme di tutti i DFD ricavati (più la descrizione dei processi elementari) descrive come avviene la gestione di un ordine nel sistema informativo del mobilificio. Un altro formalismo usato per definire le specifiche di un sistema (asincrono) sono le Reti di Petri e se siamo interessati a modellare il comportamento di un sistema in funzione del tempo possiamo fare uso dei diagrammi di transizione di stato (State Transition Diagram - STD). I&T Informatica e Telecomunicazioni SpA 71 Progettazione database relazionali Appendice B - Evoluzione dei modelli di elaborazione Oggi si parla di database su architettura client/server e su Web, ma prima di arrivare a queste soluzioni quali erano i modelli di sistema informativo utilizzati? L’evoluzione storica di tali sistemi ha visto infatti per molti anni concentrare la maggior parte delle risorse di calcolo intorno a diverse architetture di base. La prima, sia dal punto di vista temporale che da quello della rilevanza assunta, è l’architettura basata sui sistemi di calcolo centralizzati (architettura HOST). B.1 Mainframe e mini Presentandosi per primo sugli scenari dell’elaborazione dei dati, l’HOST computer (mainframe o mini) ha per lunghi anni rappresentato l’unica soluzione possibile alle richieste di elaborazione automatica di dati. L’architettura HOST è basata sul concetto di mettere a disposizione un unico sistema di elaborazione ad un numero più o meno elevato di utenti i quali possono usare ogni applicazione presente sul computer centrale richiedendola da un terminale dumb (stupido), privo di capacità di calcolo ma in grado di inviare informazioni al computer e di visualizzare quelle ricevute. Nella figura B.1 sono illustrati due modelli host-based. Si noti che l’applicazione sul mainframe e’ responsabile sia dell’interazione con l’utente che della gestione dei dati in ambiente multi-utente. Ben presto è risultato evidente che questa strategia di sviluppo di un’applicazione era inefficiente, in quanto per ogni applicazione occorreva reinventare la stessa componente di gestione dei dati. Ci fu dunque un’evoluzione che portò a dividere l’applicazione in due parti: un front end, responsabile dell’interazione con l’utente, ed un back end, responsabile della gestione dei dati. Il back end è un DBMS che può essere usato con ogni nuovo front end, con una crescita della flessibilità del sistema, in quanto più front end diversi possono accedere allo stesso DBMS. Come ogni cosa il modello host-based aveva vantaggi e svantaggi. Da una parte, poiché il sistema è centralizzato, l’amministrazione è fatta da persone affidabili che garantiscono la disponibilità dei dati agli utenti ed i backup di sicurezza; inoltre periferiche costose come unità a dischi, stampanti e modem, sono condivise tra diversi utenti. D’altra parte, al crescere del numero di utenti del sistema, deve aumentare la potenza di calcolo del computer centralizzato; i sistemi operativi proprietary, le applicazioni, la memoria e i dischi costano, e più ce ne vogliono più si paga. B.2 Modello a personal computer isolati Il modello precedente cambiò definitivamente negli anni ’80, con l’introduzione dei personal e delle workstation. Il PC IBM con il DOS, il Macintosh di Apple e, più tardi, le workstation UNIX di HP e Sun cambiarono l’informatica aziendale distribuendola in più centri di elaborazione indipendenti e mettendo fine al controllo centralizzato del mainframe su tutti i dati dell’azienda. I vantaggi introdotti da questo modello sono: • le workstation ed i personal sono molto economici e facili da usare; • possono essere personalizzati sulle esigenze dell’utente con un particolare sistema operativo e con le applicazioni più adatte; • gli applicativi per PC (word processor, spreadsheet, DBMS e pacchetti di grafica) sono tanti e poco costosi; se non soddisfano i requisiti necessari possono essere personalizzati con semplici strumenti di sviluppo; I&T Informatica e Telecomunicazioni SpA 72 Progettazione database relazionali Mainframe o minicomputer Periferiche condivise Stampante Modem DB DB DB DBMS & Applic DBMS & Applic DBMS & Applic dumb dumb dumb dumb dumb Terminali stupidi Mainframe o minicomputer Periferiche condivise Stampante DB Applic DBMS Applic Applic Modem dumb dumb dumb dumb dumb Terminali stupidi Fig. B.1 Il modello basato su un host consente a più utenti di condividere applicazioni, database e periferiche I&T Informatica e Telecomunicazioni SpA 73 Progettazione database relazionali • i dati di una workstation sono personali e l’utente è responsabile della loro gestione e della loro protezione; non è più necessario un esperto e ben retribuito system manager. D’altra parte, le informazioni aziendali, che una volta erano centralizzate, sono ora sparse in tutta l’azienda; i dati su un PC non sono immediatamente disponibili a chiunque, e questo può compromettere il guadagno nel rapporto costi/prestazioni con una caduta di produttività di gruppi di lavoro; inoltre gli utenti non possono più condividere risorse costose. La figura B.2 illustra questi problemi. Host computer DB Periferiche isolate dai PC Stampante Modem 80 80 60 60 40 40 20 20 0 0 1st Qtr 2nd Qtr DB Database isolato 1st Qtr 2nd Qtr DB Database isolato Fig. B.2 Il modello a personal computer isolati distribuisce le sorgenti di dati in tutta l’azienda B.3 Modello rete/file server I problemi citati nei paragrafi precedenti hanno condotto al modello rete/file server. Oggi chi usa un personal computer è probabilmente collegato ad una rete LAN (Local Area Network) con cui è possibile coniugare i vantaggi di un PC con la condivisione di dati e periferiche. La figura B.3 illustra questo modello. I dati sono conservati su un file server, cioè un nodo centrale accessibile a tutti gli utenti. In genere il file server è anche il punto centrale di condivisione di periferiche, code di stampa e modem. I&T Informatica e Telecomunicazioni SpA 74 Progettazione database relazionali File server Disco del file server Periferiche condivise Stampante Database Modem Grandi quantità di dati si riversano sulla rete Rete locale (LAN) Solo un utente alla volta può aggiornare il file X File X File X 80 60 File X 40 20 0 1st Qtr 2nd Qtr 80 60 40 20 0 1st Qtr 2nd Qtr 80 60 40 20 0 1st Qtr 2nd Qtr Utente C (in attesa) Utente A (usa File X) Utente B (in attesa) Fig. B.3 Il modello rete/file server collega diversi PC in modo che possano condividere dati e periferiche Poiché il file server è un computer indipendente della rete, è opportuno che sia attrezzato di una grande quantità di memoria a disco. Un’applicazione che gira su una workstation legge e scrive sul file server; in molti casi interi file viaggiano sulla rete per servire le operazioni dei vari PC. Ad esempio, l’utente può avere un DBMS sul suo PC e, dopo averlo lanciato, può chiedere le informazioni che si trovano in un file sul file server, il quale invia tutto o in parte il file che le contiene e poi si disinteressa dell’applicazione che gira sul PC dell’utente. Alla fine l’utente salva il file sul file server. Purtroppo il modello rete/file server è congenitamente incapace di servire adeguatamente applicazioni multi-utente a dati condivisi, come invece avviene su mainframe. Prima di tutto non consente la concorrenza (accesso simultaneo ad un singolo insieme di dati da più utenti) richiesta dalle applicazioni multi-user; questo perché il file server gestisce file, grossi insiemi di dati, e non permette ad un utente di usare un file che sia stato locked (bloccato) da un altro utente. In altre parole, utenti che operano sullo stesso insieme di dati si scontrano e sono costretti ad attendere in linea. Inoltre, se molte workstation richiedono ed inviano file, la rete si satura rapidamente e la performance del sistema subisce un notevole peggioramento. I&T Informatica e Telecomunicazioni SpA 75 Progettazione database relazionali B.4 Modello client/server I problemi delle LAN hanno inoltre portato all’introduzione del modello client/server, chiamato anche elaborazione distribuita o elaborazione cooperativa, che coniuga i vantaggi della rete con le caratteristiche di accesso condiviso e alte performance tipiche del modello host-based (vedi figura B.4). Il modello client/server è costituito da tre parti, ognuna con un compito specifico: un server back end che si occupa di gestire in modo efficiente un database tra più utenti che richiedono l’accesso concorrente, una parte client front end usata dall’utente per interagire con i dati, una rete e un software di comunicazione che costituiscono i veicoli che trasmettono i dati tra client e server. Un sistema client/server si basa su una corretta suddivisione di una applicazione in componenti client e componenti server. Il paradigma applicativo che ha costituito un riferimento in questo contesto è illustrato nella figura B.5. Server di database Periferiche condivise Stampante Database condiviso Modem Piccole quantità di dati consentono che la LAN lavori in modo efficiente Rete locale (LAN) Molti utenti possono aggiornare la stessa tabella contemporaneamente Riga Z Riga X 80 60 40 20 0 1st Qtr Client 2nd Qtr Riga Y 80 60 40 20 0 1st Qtr 2nd Qtr 80 60 40 20 0 1st Qtr 2nd Qtr Utente C (usa riga Z) Utente A (usa riga X) Utente B (usa riga Y) Fig. B.4 I database client/server condividono i dati in piccoli insiemi (righe) che consentono un alto grado di concorrenza e di performance I&T Informatica e Telecomunicazioni SpA 76 Progettazione database relazionali Interfaccia utente Logica applicativa Logica di accesso ai dati Accesso ai dati Fig. B.5 Struttura di una applicazione client/server E’ovvio che suddividere logicamente un’applicazione in componenti funzionali rappresenta sempre un’operazione arbitraria, ma considerare l’applicazione come composta dai quattro moduli sopra evidenziati ha consentito un approccio molto più corretto alle problematiche client/server. Analizziamo in dettaglio ogni singolo modulo per poter cogliere meglio le implicazioni connesse. Interfaccia utente In questo modulo rientrano tutti i componenti applicativi che consentono all’utilizzatore del programma di interagire con esso per ottenere determinati risultati. La più semplice interfaccia pensabile per un modulo software è quella che consiste semplicemente nella possibilità del suo richiamo, tramite un idoneo meccanismo fornito dal sistema operativo, e nell’utilizzo dei risultati della sua esecuzione, come una stampa, una videata, un file archiviato su qualche supporto. Ci aspettiamo ovviamente che un’applicazione moderna sia realizzata in ambiente grafico, in conformità a determinati standard e sia progettata per facilitare realmente il suo utilizzo da parte dell’utente finale. Una buona interfaccia deve addirittura essere in grado di far cogliere all’utente tutte le potenzialità del sistema che sta utilizzando al di là di quelle che sono le sue immediate necessità. Logica applicativa Le componenti applicative che fanno sì che l’esecuzione di un programma porti a determinati risultati rientrano in questa categoria. Può essere costituita da componenti di calcolo, di stampa, di elaborazione di un testo o di quanto altro realizza la funzione per la quale l’utente ha richiamato in esecuzione un determinato componente software. Logica di accesso ai dati L’identificazione di questa componente ha contribuito alla corretta definizione di una applicazione realizzata secondo il paradigma client/server. Si tratta di fatto di tutti quegli elementi che gestiscono in maniera corretta i dati forniti dall’utente al sistema o viceversa reperiti per la loro consultazione dai rapporti di archiviazione. Fanno parte della logica di accesso ai dati tutte le procedure di controllo sui dati stessi, da una semplice validazione, come può essere quella su un valore minimo o massimo, a procedure di controllo della validità dei riferimenti tra i dati. Possono in certi casi esistere procedure complesse che producono operazioni in cascata a seguito di particolari eventi, come il calcolo di valori derivati dall’inserimento di una specifica tabella o la registrazione di valori di controllo quali l’identità dell’utente, la data e l’ora dell’operazione relativamente all’esecuzione di operazioni ritenute critiche. Accesso ai dati In questo gruppo rientrano tutte le componenti che si occupano di archiviare e reperire i dati sui supporti di archiviazione del sistema. Queste operazioni sono normalmente svolte da un DBMS dovendo essere fornite garanzie di integrità fisica dei dati, possibilità di accesso concorrente, ottimizzazione dei tempi di lettura e scrittura e indipendenza nei confronti del sistema hardware utilizzato. Alla luce di quanto detto risulta che la suddivisione ottimale dei componenti di un sistema client/server può risultare quella illustrata in figura B.6. I&T Informatica e Telecomunicazioni SpA 77 Progettazione database relazionali Componenti server Componenti client Interfaccia utente Logica applicativa Logica di accesso ai dati Accesso ai dati Fig. B.6 Suddivisione di una applicazione client/server L’intersezione tra componenti client e componenti server indica la forte difficoltà esistente in un sistema reale a definire una netta distinzione tra le due classi di componenti. Risulta infatti estremamente complesso suddividere la logica di accesso ai dati dalla logica applicativa per molte delle applicazioni di un sistema reale. Normalmente è necessario che alcuni di questi componenti vengano replicati sia sul lato client che su quello server per poter garantire al tempo stesso integrità nei dati ed interfacce utenti efficaci. Un caso significativo è quello tipico sui controlli di validità del singolo dato: sebbene debba essere sicuramente implementato un meccanismo che protegga il database dall’accettare valori incongruenti, è altrettanto vero che una buona interfaccia utente dovrà intercettare possibili errori di inserimento dati se non guidare l’utente verso l’inserimento di dati corretti. A questo scopo la logica di controllo dovrà essere parzialmente duplicata su vari componenti dell’applicazione. Ad evitare inconsistenze, i controlli sull’integrità del dato dovranno sempre essere implementati sul lato server; tuttavia una buona logica applicativa dovrà comprendere dei meccanismi per acquisire in maniera automatica e dinamica dal server le informazioni relative ai vincoli di integrità del dato stesso per poterli riprodurre in locale, possibilmente passando tali informazioni ai componenti di interfaccia progettati per guidare l’utente nella fase di immissione dei dati. Sebbene l’ultima parola in fatto di controlli spetti al server, sarebbe di fatto assurdo che nessun controllo fosse fatto a livello dell’applicazione client. Avremmo in questo caso un’elevata quantità di dati rifiutati durante le fasi di inserimento e modifica e di fatto caricheremmo l'utente dell'onere di conoscere tutti i vincoli definiti all’interno dello schema del database. La suddivisione in componenti client e server illustrata si collega anche alla necessità di un moderno database di poter gestire vincoli di integrità logica sui dati oltre a quelli di integrità fisica. I DBMS appositamente progettati, o comunque profondamente rivisti nel contesto di architetture client/server, vengono in certi casi definiti estesi proprio per sottolineare la presenza di meccanismi idonei a definire vincoli di integrità dei dati in essi archiviati. Parte di questi meccanismi sono in realtà implementati anche nei database commerciali per sistemi centralizzati. In particolare la struttura stessa del sistema relazionale aveva portato i progettisti di questi prodotti, già nei primi anni del loro utilizzo, alla ricerca di meccanismi per mantenere integri i vincoli di riferimento tra le varie tabelle del database. Tuttavia non era apparso chiaro, o perlomeno rilevante che i vincoli di integrità referenziale sono solo una parte, seppure significativa, della classe più ampia dei vincoli di integrità logica dei dati. Tale visione era certamente condizionata da un approccio nello sviluppo dei sistemi informativi orientato più ai programmi che non ai dati, tipico del periodo antecedente all’uso dei DBMS. Questo modo di pensare è nato dalla mancata percezione della necessità di indipendenza tra il dato e l’applicazione e ha portato a considerare i vincoli di integrità sui dati come parte della logica applicativa, da implementare quindi come controlli da inserire in un programma. Le caratteristiche di distribuzione e maggiore flessibilità del sistema client/server fanno sì che un dato venga normalmente visto come patrimonio I&T Informatica e Telecomunicazioni SpA 78 Progettazione database relazionali comune di molte applicazioni, rendendo di fatto impossibile un approccio di controllo sulla validità del dato stesso implementata su ogni singolo componente software. Si rendono quindi necessari meccanismi a livello di DBMS per la definizione a livello centralizzato, come parte integrante del dato, dei necessari vincoli di integrità logica. Facendo riferimento alla definizione classica che definisce un’informazione come un dato integrato dalle conoscenze necessarie per interpretarlo, potremmo dire che i DBMS stessi sono più dei gestori di informazioni che gestori di dati. Secondo lo schema già visto potremmo affermare che in un DBMS esteso esistono dei meccanismi che implementano l’approccio della figura B.7. Componenti server Componenti client Interfaccia utente Logica applicativa Logica di accesso ai dati Accesso ai dati Integrità di comportamento Integrità referenziale Integrità di dominio Fig. B.7 Logica di accesso dati e integrità semantica La logica di accesso ai dati, definita come componente chiave di un sistema client/server, coincide infatti con i meccanismi definiti per garantire l’integrità dei dati sui DBMS. A questo livello, quindi, viene gestita l’integrità referenziale, cioè viene gestito l’insieme di regole utilizzate per assicurare che le relazioni tra i record delle tabelle correlate siano valide e non vengano eliminati o modificati per errore dati correlati; viene inoltre garantita l’integrità di dominio, cioè si controlla che i dati che si vogliono inserire nel database appartengano al loro dominio di definizione (cioè se appartengono ad un insieme specifico di valori, definito al momento della creazione delle tabelle del DB in cui devono essere inseriti). Infine vengono effettuati anche i controlli per garantire l’integrità di comportamento, argomento considerato di particolare interesse per i sistemi informativi moderni, connesso alla visione del dato come correlato a particolari regole di comportamento (ad esempio, nell’inserimento di un ordine è opportuno assicurarsi che la sua data non sia antecedente ad ordini precedentemente emessi). L’implementazione di questi vincoli può avvenire sia sfruttando la sintassi standard SQL, che ha però il forte limite nella necessità di basarsi su definizioni espresse al momento della creazione delle strutture dati direttamente sulle colonne o nelle tabelle del database, sia con un approccio di tipo procedurale, che consente di realizzare moduli software direttamente all’interno del DBMS per effettuare operazioni di controllo su determinati eventi del sistema. Il meccanismo principale di gestione dell’integrità logica dei dati tramite la tecnica procedurale è quello del trigger, un insieme di istruzioni che vengono eseguite non ad una richiesta specifica dell’utente ma al determinarsi di particolari eventi. I&T Informatica e Telecomunicazioni SpA 79 Progettazione database relazionali Un sistema client/server può raggiungere prestazioni migliori di un sistema file server, perché sia l’applicazione client che il server di database collaborano a sostenere il carico di elaborazione di un’applicazione (da cui il termine “elaborazione distribuita”). Il server gestisce il database tra diversi client, mentre i client inviano, richiedono e analizzano i dati che ricevono dal server. L’applicazione client lavora con piccoli insiemi specifici di dati, come ad esempio le righe di una tabella, e non con file, come avviene invece nel sistema file server. Un server di database è intelligente, blocca e restituisce solo le righe che un client richiede, il che garantisce la concorrenza, minimizza il traffico di rete e migliora la performance. B.5 Pregi e difetti del modello client/server Flessibilità dell’elaborazione distribuita I vantaggi maggiori derivano dal fatto che il client e il server girano su diversi computer e quindi i computer possono essere scelti con requisiti particolari per soddisfare al meglio le esigenze delle due componenti. Per esempio, è consigliabile usare processori potenti e grandi quantità di memoria, centrale o su disco, per il server, che così può conservare grandi quantità di dati e servire molti utenti. Invece si può usare un computer meno costoso, con poca memoria ed una CPU non tanto potente, ma un mouse ed eccellenti capacità grafiche, per applicazioni client. Inoltre il sistema può rispondere con flessibilità agli inevitabili cambiamenti del software e dell’hardware. Infine le dimensioni del sistema possono essere modificate in corrispondenza a cambiamenti dei gruppi di lavoro, ad esempio aggiungendo nuove workstation per i nuovi assunti. Client/server per concentrarsi su un’area dello sviluppo del sistema Ogni componente può essere specializzata per fare qualcosa nel modo migliore. Per esempio, nello sviluppo di un’applicazione client il programmatore può concentrarsi sulla presentazione e sull’analisi dei dati, mentre il server si occupa della loro gestione; in altre parole il programmatore non deve costruire un nuovo DBMS ogni volta che crea una nuova applicazione. Client/server per risparmiare Nel passato l’unico modo per eseguire un’applicazione su un database multi-utente era quello di usare mainframe o mini costosi e potenti. Questo comportava terminali a carattere, un team di programmatori ben pagati per la messa a punto dell’applicazione ed un team di amministratori, anche loro ben pagati, per la manutenzione. Le spese iniziali e di manutenzione per questo sistema potevano essere astronomiche. In molti casi, un sistema client/server supporta un’applicazione da mainframe con costi molto ridotti, distribuendo la potenza di calcolo su molti computer economici collegati in rete. Anche lo sviluppo dell’applicazione è più semplice, grazie alle interfacce GUI (Graphical User Interface) e ai tool di sviluppo orientati agli oggetti. Alcuni svantaggi Per quanto riguarda gli svantaggi, è da considerare che la riduzione di costi potrebbe non essere significativa nella realtà. Quando si preventivano i costi per un sistema bisogna tenere conto di molti fattori, e non solo delle spese per l’hardware: per esempio la produttività degli utenti, sia quelli che usano gli applicativi, sia quelli che sviluppano software, sia quelli che amministrano il sistema. Chi sviluppa software aumenterà la sua produttività grazie alle interfacce GUI ed ai tool CASE (Computer Aided Software Engineering) disponibili nel modello client/server, mentre gli utenti di applicativi e gli amministratori possono vedere diminuire la loro produttività. Infatti, l’affidabilità di un sistema client/server, fatto da un mix di componenti hardware e software sviluppate e gestite in modo indipendente, è intrinsecamente minore di quella di un mainframe o di I&T Informatica e Telecomunicazioni SpA 80 Progettazione database relazionali un mini centralizzato. E poi, chi chiamare in caso di guasto? Il tempo di down dovuto alla “scarsa affidabilità” si traduce in una diminuzione di produttività degli utenti finali e degli amministratori. Il segreto per realizzare davvero un risparmio sta nella scelta del tipo corretto di applicazioni che possono girare con successo su un sistema client server. I&T Informatica e Telecomunicazioni SpA 81 Progettazione database relazionali Bibliografia Ullman J. D. - Basi di dati e basi di conoscenza – Jackson, 1991. Atzeni P., Ceri S., Paraboschi S., Torlone R. – Basi di dati. Concetti, Linguaggi e architetture. – McGraw-Hill, 1996. Guidi A., Dordolò D. – SQL – McGraw-Hill, 1996. Yourdon E. – Analisi strutturata dei sistemi. Concetti e metodi. – Jackson, 1990. Bobrowski S. – La granda guida a Oracle 7 – Jackson, 1995. Ozsu M. T. – Query Processing Issues in OO KBS, 1994. http://www.cs.usask.ca/homepages/grads/moa135/826/DD-sum.html Decker H., Teniente E., Urpì T. – How to Tackle Schema Validation by View Updating Costal D., Teniente E., Urpì T., Farrè C. – Handling Conceptual Model Validation by Planning I&T Informatica e Telecomunicazioni SpA 82