Uno schema del database è un progetto che definisce come sono organizzati i dati – classi, colonne, tipi e relazioni, ma non i dati stessi. La trinità in una riga che vale la pena ricordare: lo schema è il progetto, un’istanza sono i dati in un dato momento, e il database è l’intero edificio. I progetti cambiano raramente e in modo deliberato; le stanze, invece, si riempiono di continuo.
Punti chiave
| Domanda | Risposta |
|---|---|
| Che cos’è | La struttura come metadati: tabelle/classi, colonne tipizzate, chiavi, vincoli |
| Che cosa non è | I dati – quelli sono l’istanza, che cambia a ogni scrittura |
| Le tre altitudini | Logica (progettazione) · fisica (archiviazione) · vista (ciò che vede chi consuma) |
| “Schemaless”? | Un abuso di linguaggio – lo schema-on-read sposta solo l’imposizione al momento della query |
| Come evolve | Migrazioni: modifiche versionate, scriptate, revisionabili |
Il progetto, messo per iscritto
Uno schema nella sua lingua madre – due tabelle, chiavi, un vincolo, un indice e una vista, che è quasi tutto il vocabolario:
CREATE TABLE users (
id bigserial PRIMARY KEY,
email text NOT NULL UNIQUE, -- vincolo: niente duplicati
role text NOT NULL DEFAULT 'member'
);
CREATE TABLE orders (
id bigserial PRIMARY KEY,
user_id bigint NOT NULL REFERENCES users(id), -- relazione
total numeric(10,2) CHECK (total >= 0), -- regola che i dati devono rispettare
placed timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX orders_by_user ON orders (user_id, placed); -- livello fisico
CREATE VIEW recent_orders AS -- livello delle viste
SELECT * FROM orders WHERE placed > now() - interval '30 days';
Lo stesso progetto su una piattaforma a schema flessibile cresce da ciò che si salva – colonne tipizzate dedotte alla prima scrittura, visibili subito in una dashboard:
// JavaScript / Node.js — Back4app JS SDK
// The schema grows typed columns from what you save
const event = new Parse.Object('Event');
event.set('name', 'Launch day'); // String
event.set('seats', 120); // Number
event.set('startsAt', new Date('2026-09-01T18:00:00Z')); // Date
event.set('venue', new Parse.GeoPoint(38.72, -9.14)); // GeoPoint
await event.save(); // columns exist, typed, visible in the dashboard // Flutter / Dart — Back4app Flutter SDK
// The schema grows typed columns from what you save
final event = ParseObject('Event')
..set('name', 'Launch day') // String
..set('seats', 120) // Number
..set('startsAt', DateTime.parse('2026-09-01T18:00:00Z')) // Date
..set('venue', ParseGeoPoint(latitude: 38.72, longitude: -9.14));
await event.save(); // columns exist, typed, visible in the dashboard // iOS / Swift — Back4app Swift SDK
// The schema is a typed struct — columns mirror the model
struct Event: ParseObject {
var objectId: String?; var createdAt: Date?
var updatedAt: Date?; var ACL: ParseACL?; var originalData: Data?
var name: String? // String column
var seats: Int? // Number column
var startsAt: Date? // Date column
var venue: ParseGeoPoint? // GeoPoint column
}
var event = Event(); event.name = "Launch day"; event.seats = 120
event.save { _ in } // columns exist, typed, visible in the dashboard // Android / Kotlin — Back4app Android SDK
// The schema grows typed columns from what you save
val event = ParseObject("Event").apply {
put("name", "Launch day") // String
put("seats", 120) // Number
put("startsAt", Date()) // Date
put("venue", ParseGeoPoint(38.72, -9.14)) // GeoPoint
}
event.saveInBackground() // columns exist, typed, visible in the dashboard Logico vs. fisico vs. vista
| Distinzione | Questo | vs. quello |
|---|---|---|
| Schema vs. istanza | Il progetto, cambia raramente | L’istantanea dei dati, cambia di continuo |
| Logico vs. fisico | Progettazione indipendente dal motore | Decisioni di archiviazione legate al motore |
| Progetto vs. namespace | Lo “schema” dell’applicazione | CREATE SCHEMA – un contenitore di oggetti con nome e permessi |
| Schema-on-write vs. on-read | Validato prima che i dati atterrino (relazionale) | Imposto al momento dell’uso (predefinito documentale) |
| Transazionale vs. analitico | Schemi applicativi normalizzati | Forme star/snowflake costruite per l’aggregazione |
La terza riga disinnesca un’ambiguità reale che gran parte delle spiegazioni salta: in alcuni motori la parola nomina anche un namespace – un contenitore di tabelle con permessi – così “lo schema” può indicare il progetto dell’applicazione o una cartella dentro il database, e decide il contesto.
Schema-on-write vs. schema-on-read
I database “schemaless” hanno uno schema – solo che lo fanno pagare in un altro modo. Lo schema-on-write valida la struttura prima che i dati atterrino: tipo sbagliato, campo mancante, riferimento rotto – respinti alla porta. Lo schema-on-read accetta le scritture in modo flessibile e impone le aspettative quando i dati vengono usati – iterazione più rapida, e ogni lettore diventa un validatore. La posizione moderna è una manopola, non una guerra: le piattaforme documentali aggiungono la validazione, i motori relazionali aggiungono colonne JSON, e i backend gestiti fanno a metà – tipi dedotti e imposti per colonna, mentre nuove colonne compaiono senza la cerimonia di una migrazione. La questione del rigore è in realtà una questione di proprietà: chi trova il record malformato, il database al momento della scrittura o il proprio codice alle 2 di notte?
Come evolvono gli schemi
Il progetto sopravvive alla sua prima stesura, e le migrazioni sono il modo in cui cambia senza caos: ogni modifica allo schema è uno script versionato – aggiungere la colonna, riempirla a posteriori, stringere il vincolo – applicato nell’ordine giusto, in ogni ambiente, revisionato come il codice che ne dipende. Due discipline portano quasi tutto il valore: rendere le modifiche retrocompatibili nella finestra in cui codice vecchio e nuovo convivono (aggiungere, poi migrare, poi rimuovere – mai rinominare sul posto), e tenere la versione dello schema nel repository perché codice e struttura viaggino insieme. Sulle piattaforme gestite da dashboard vale la stessa disciplina con strumenti diversi: far evolvere lo schema visivamente, ma di proposito, con le modifiche guidate dal client disattivate in produzione.
Casi d’uso tipici
- Progettare un nuovo backend. Lo schema è l’output della modellazione dei dati: entità e archi diventano classi, colonne e chiavi.
- Imporre l’integrità. Vincoli come regole eseguibili – totali non negativi, e-mail univoche – intercettati dal motore, non dalle segnalazioni di bug.
- Contratto di squadra. Lo schema è il vocabolario condiviso tra backend, frontend e analytics; un diagramma entità-relazione è documentazione che non può andare alla deriva.
- Lavoro preparatorio sulle prestazioni. Indici e disposizione fisica – il piano inferiore dello schema – decidono quali query restano rapide su larga scala.
- Superficie di sicurezza. I permessi a livello di schema regolano chi può fare che cosa su ogni classe: struttura e controllo degli accessi in un unico posto.
Quanto deve essere rigido lo schema? Matrice decisionale
| Preferire il rigore (schema-on-write) quando… | Preferire la flessibilità (inferenza + validazione) quando… |
|---|---|
| Gli errori sui dati costano (denaro, magazzino) | Si itera sul prodotto ogni settimana |
| Molti scrittori, un solo contratto | Un unico team possiede sia il codice sia i dati |
| L’analytics dipende da colonne stabili | I campi variano davvero da record a record |
| I vincoli codificano regole di business | Le regole vivono comunque nella validazione lato server |
| Le migrazioni sono routine per il team | La cerimonia della migrazione rallenterebbe l’esplorazione |
Il valore predefinito pragmatico per i backend applicativi: flessibile mentre si impara, irrobustito al momento del rilascio – dedurre lo schema durante lo sviluppo, poi congelarlo (nessuna modifica allo schema dal client, aggiunta di campi disattivata) il giorno in cui arrivano gli utenti reali.
Limiti e trade-off
- Lo schema congela le ipotesi. Ogni decisione su tipo di colonna e cardinalità costa poco oggi ed è una migrazione domani – conviene progettare per la taglia successiva.
- Il rigore tassa l’iterazione. Ogni esperimento paga il pedaggio della migrazione; è il prezzo delle garanzie, non un difetto.
- La flessibilità tassa i lettori. Lo schema-on-read sposta la validazione in ogni consumatore; senza disciplina, “flessibile” diventa “cinque forme dello stesso record”.
- Il livello fisico è invisibile finché non lo è. Indici e disposizione non cambiano la correttezza – solo se le query sopravvivono alla crescita.
- I permessi su un namespace non sono progettazione.
CREATE SCHEMAorganizza gli oggetti e ne regola l’accesso; non rende buono il progetto.
Lo schema su Back4app
Back4app è una piattaforma open-source di Backend as a Service (BaaS) che combina database gestito, API REST e GraphQL generate automaticamente, autenticazione, archiviazione di file e funzioni serverless con Cloud Code. Lo schema è una superficie di prima classe e visibile: si definiscono classi e colonne tipizzate nella dashboard, oppure si lascia che il primo salvataggio le deduca – i tab di codice qui sopra creano colonne tipizzate reali, con objectId, createdAt, updatedAt e un’ACL aggiunti per impostazione predefinita a ogni classe. Tutto ciò che lo schema dichiara si riflette all’istante nelle API generate automaticamente, è protetto dai permessi a livello di classe ed è esplorabile nella dashboard visuale – il progetto, l’imposizione delle regole e la documentazione come un unico artefatto.
Domande frequenti
Che cos'è uno schema del database in parole semplici?
Il progetto di un database: quali tabelle o classi esistono, quali colonne portano, il tipo di ogni colonna, le chiavi e i vincoli, e come i record si collegano tra loro. Sono metadati – la struttura, non i dati archiviati. Cambiare lo schema significa cambiare la forma che i dati possono assumere; i dati stessi vivono dentro quella forma.
Qual è la differenza tra uno schema, un database e un'istanza?
Tre livelli di zoom. Il database è il sistema intero – il motore più i dati archiviati. Lo schema ne è la struttura formale, che cambia raramente e in modo deliberato. Un'istanza sono i dati reali in un dato momento, che cambiano a ogni scrittura. Uno schema, un database, infinite istanze nel tempo.
Qual è la differenza tra uno schema logico e uno fisico?
Lo schema logico è la progettazione indipendente dal motore: entità, attributi, relazioni, vincoli – ciò che disegna un diagramma entità-relazione. Lo schema fisico è il modo in cui quella progettazione atterra in un motore preciso: organizzazione dell'archiviazione, indici, partizioni. Un terzo livello, lo schema di vista (o esterno), definisce ciò che vede ciascun consumatore. Stessa progettazione, tre altitudini.
Che cosa contiene davvero uno schema?
Gli oggetti dello schema: tabelle o classi, colonne con i loro tipi di dato, chiavi primarie ed esterne, vincoli come NOT NULL, UNIQUE e CHECK, indici e viste. In alcuni motori "schema" ha anche un secondo significato – un namespace con un nome che raggruppa questi oggetti e porta i permessi di accesso, che è precisamente ciò che crea CREATE SCHEMA.
I database NoSQL hanno uno schema?
"Schemaless" è un abuso di linguaggio: lo schema esiste sempre; la domanda è chi lo impone, e quando. I motori relazionali sono schema-on-write: la struttura viene validata prima che i dati atterrino. Gli archivi documentali adottano per impostazione predefinita lo schema-on-read: la struttura vive nelle aspettative dell'applicazione e viene verificata solo all'uso. Oggi la maggior parte delle piattaforme documentali supporta anche la validazione, il che fa del rigore una manopola invece di una dicotomia.
Che cos'è una migrazione di schema?
Una modifica allo schema versionata e scriptata – aggiungere una colonna, stringere un vincolo – applicata in modo incrementale e nell'ordine giusto su tutti gli ambienti. Le migrazioni sono il modo in cui gli schemi evolvono senza caos: ogni modifica è revisionabile, ripetibile e reversibile, e la versione dello schema viaggia con la codebase che la aspetta.
Che cosa sono gli schemi a stella e a fiocco di neve?
Forme di schema tipiche dell'analytics. Uno schema a stella (star) mette una tabella dei fatti centrale (eventi, vendite) in mezzo a tabelle delle dimensioni denormalizzate – pochi join, aggregazione rapida. Uno schema a fiocco di neve (snowflake) normalizza quelle dimensioni in sotto-tabelle – meno ridondanza, più join. Ottimizzano i carichi di reporting e sono cugini, non concorrenti, degli schemi transazionali usati dai backend applicativi.
Come si definisce uno schema su un Backend as a Service?
In due modi complementari: visivamente – classi e colonne tipizzate create in una dashboard – e per inferenza, dove il salvataggio del primo oggetto crea automaticamente la classe e le colonne tipizzate, con campi predefiniti come objectId, createdAt, updatedAt e un'ACL aggiunti dalla piattaforma. L'irrobustimento per la produzione poi lo congela: modifiche allo schema guidate dal client disattivate, evoluzione successiva dalla dashboard, di proposito.