Panoramica degli schemi

Questa pagina illustra i requisiti dello schema di Spanner e come utilizzare lo schema per creare relazioni gerarchiche e funzionalità dello schema. Inoltre, introduce con interleaving, che possono migliorare le prestazioni delle query quando si eseguono query sulle tabelle in una relazione genitore-figlio.

Uno schema è uno spazio dei nomi che contiene oggetti di database, come tabelle, visualizzazioni, indici e funzioni. Puoi usare gli schemi per organizzare gli oggetti, applicare un controllo dell'accesso granulare ed evitare collisioni di nomi. Devi definire uno schema per ogni database in Spanner.

Puoi anche segmentare ulteriormente e archiviare le righe nella tabella del database in diverse regioni geografiche. Per ulteriori informazioni, consulta Panoramica del partizionamento geografico.

Dati fortemente tipizzati

I dati in Spanner sono fortemente tipizzati. I tipi di dati includono scalari e complessi descritti in Tipi di dati in GoogleSQL e i tipi di dati di PostgreSQL.

Scegli una chiave principale

I database Spanner possono contenere una o più tabelle. Le tabelle sono strutturate come righe e colonne. Lo schema della tabella definisce una o più colonne della tabella come la chiave primaria della tabella che identifica in modo univoco ogni riga. Le chiavi principali sono sempre indicizzate per la ricerca rapida delle righe. Se vuoi aggiornare o eliminare righe esistenti in una tabella, la tabella deve avere una chiave primaria. Una tabella senza principale le colonne chiave possono avere una sola riga. Solo i database di dialetti GoogleSQL possono avere senza chiave primaria.

Spesso la tua applicazione ha già un campo che è adatto per l'utilizzo come chiave primaria. Ad esempio, per una tabella Customers potrebbe essere presente un CustomerId fornito dall'applicazione che funge da chiave primaria. In altri casi, potrebbe essere necessario generare una chiave primaria durante l'inserimento della riga. In genere si tratta di un valore intero univoco senza significato commerciale (una chiave primaria surrogata).

In ogni caso, devi fare attenzione a non creare hot spot con la scelta della chiave primaria. Ad esempio, se inserisci record con un numero intero in aumento monotonico come chiave, lo inserirai sempre alla fine dello spazio della chiave. Questo comportamento è indesiderato perché Spanner divide i dati tra per intervalli di chiavi, il che significa che gli inserimenti saranno indirizzati a un singolo server, creando un hotspot. Esistono tecniche che possono distribuire il carico su più server ed evitare hotspot:

Relazioni tabella padre-figlio

Esistono due modi per definire le relazioni padre-figlio in Spanner: interfoliazione delle tabelle e chiavi esterne.

L'interleaving delle tabelle di Spanner è una buona scelta per molte relazioni padre-figlio. Con l'interleaving, Spanner colloca le righe figlio con righe padre nello spazio di archiviazione. La colocation può significativamente a migliorare le prestazioni. Ad esempio, se hai una tabella Customers e una Invoices e la tua applicazione recupera spesso tutte le fatture per un puoi definire Invoices come tabella secondaria con interleaving Customers. In questo modo dichiari una relazione di località dei dati tra due tabelle indipendenti. Stai dicendo a Spanner di memorizzare una o più righe di Invoices con una riga Customers.

Per associare una tabella secondaria a una tabella padre, utilizza un DDL che dichiara tabella secondaria con interleaving in quella padre e includendo la tabella padre chiave primaria come prima parte della chiave primaria composita della tabella figlio. Per maggiori informazioni Informazioni sull'interfoliazione, consulta Creare tabelle con interleaving più avanti in questo .

Le chiavi esterne sono una soluzione padre-figlio più generica e sono adatte a ulteriori casi d'uso. Non si limitano alle colonne di chiave primaria e le tabelle possono avere più relazioni di chiave esterna, sia come genitore in alcune relazioni che come figlio altri. Tuttavia, una relazione di chiave esterna non implica la collocazione delle tabelle nel livello di archiviazione.

Google consiglia di scegliere di rappresentare le relazioni padre-figlio come tabelle con interleaving o come chiavi esterne, ma non entrambi. Per ulteriori informazioni sulle chiavi esterne e sul loro confronto con le tabelle con interleaving, consulta la Panoramica delle chiavi esterne.

Chiavi primarie nelle tabelle con interfoliazione

Per l'interlacciamento, ogni tabella deve avere una chiave primaria. Se dichiari una tabella essere un elemento figlio con interleaving di un'altra tabella, la tabella deve avere un chiave primaria che include tutti i componenti della chiave primaria dell'elemento padre, in nello stesso ordine e, in genere, in una o più colonne secondarie aggiuntive della tabella.

Spanner archivia le righe in ordine ordinato in base ai valori della chiave primaria, con righe secondarie inserite tra le righe principali. Guarda un'illustrazione di righe con interleaving in Crea tabelle con interleaving più avanti in questa pagina.

In sintesi, Spanner può collocare fisicamente le righe di tabelle correlate. Gli esempi di schema mostrano l'aspetto di questo layout fisico.

Suddivisione del database

Puoi definire gerarchie di relazioni padre-figlio con interleaving fino a sette livelli di profondità, il che significa che puoi collocare in modo colocalizzato le righe di sette tabelle indipendenti. Se la dimensione dei dati nelle tabelle è ridotta, un singolo Spanner in grado di gestire il database. Ma cosa succede quando le tabelle correlate crescono e iniziano a raggiungere i limiti di risorse di un singolo server? Spanner è un database distribuito, il che significa che, cresce, Spanner suddivide i dati in blocchi chiamati "divisioni". I singoli split possono spostarsi indipendentemente l'uno dall'altro e essere assegnati a server diversi, che possono trovarsi in località fisiche diverse. R che contiene un intervallo di righe contigue. Le chiavi iniziale e finale di questo intervallo sono chiamati "confini della suddivisione". Spanner aggiunge e rimuove automaticamente confini della suddivisione in base alle dimensioni e al carico, il che cambia il numero di suddivisioni in del database.

Suddivisione basata sul carico

Ecco un esempio di come Spanner esegue la suddivisione basata sul carico mitigazione degli hotspot di lettura, supponiamo che il database contenga una tabella con 10 righe vengono lette più spesso di tutte le altre righe della tabella. Spanner può aggiungere limiti di suddivisione tra ciascuna di queste 10 righe in modo che ciascuna venga gestita da un server diverso, anziché consentire a tutte le letture di queste righe di consumare le risorse di un singolo server.

Come regola generale, se segui le best practice per la progettazione dello schema, Spanner può mitigare gli hotspot in modo che la velocità effettiva di lettura dovrebbe migliorare a intervalli di pochi minuti fino a quando non saturare le risorse nel tuo o si verificano casi in cui non è possibile aggiungere nuovi confini della suddivisione (perché abbiamo una suddivisione che copre una sola riga senza elementi secondari con interleaving).

Schemi denominati

Gli schemi denominati consentono di organizzare insieme dati simili. In questo modo puoi trovare rapidamente gli oggetti nella console Google Cloud, applicare i privilegi ed evitare collisioni di nomi.

Gli schemi denominati, come altri oggetti del database, vengono gestiti utilizzando DDL.

Gli schemi denominati di Spanner ti consentono di utilizzare nomi completi (FQN) per eseguire query sui dati. I nomi di dominio completi consentono di combinare il nome dello schema per identificare gli oggetti del database. Ad esempio, puoi creare uno schema chiamato warehouse per l'unità commerciale del magazzino. Le tabelle che utilizzano questo lo schema potrebbe includere: product, order e customer information. In alternativa, puoi creare uno schema denominato fulfillment per l'unità commerciale di evasione degli ordini. Questo schema può anche contenere tabelle chiamate product, order e customer information. Nel primo esempio, il nome di dominio completo è warehouse.product e nel secondo esempio è fulfillment.product. In questo modo eviterai confusione situazioni in cui più oggetti hanno lo stesso nome.

Nel DDL CREATE SCHEMA, agli oggetti della tabella viene assegnato sia un nome di dominio completo, ad esempio sales.customers e un nome breve, ad esempio sales.

I seguenti oggetti database supportano gli schemi denominati:

  • TABLE
    • CREATE
    • INTERLEAVE IN [PARENT]
    • FOREIGN KEY
    • SYNONYM
  • VIEW
  • INDEX
  • FOREIGN KEY
  • SEQUENCE

Per ulteriori informazioni sull'utilizzo degli schemi denominati, consulta Gestire gli schemi denominati.

Utilizza un controllo dell'accesso granulare con schemi denominati

Gli schemi con nome ti consentono di concedere l'accesso a livello di schema a ogni oggetto dello schema. Questo vale per gli oggetti dello schema esistenti al momento in cui concedi l'accesso. Devi concedere l'accesso agli oggetti aggiunti in un secondo momento.

Il controllo dell'accesso granulare limita l'accesso a interi gruppi di oggetti di database, ad esempio tabelle, colonne e righe della tabella.

Per ulteriori informazioni, vedi Concedere i privilegi di controllo dell'accesso granulare agli schemi nominativi.

Esempi di schema

Gli esempi di schema in questa sezione mostrano come creare tabelle principali e secondarie con e senza interlacciamento e illustrano i layout fisici corrispondenti dei dati.

Crea una tabella padre

Supponiamo che tu stia creando un'applicazione musicale e che tu abbia bisogno di una tabella che memorizzi righe di dati sui cantanti:

Tabella Cantanti con cinque righe e quattro colonne

Tieni presente che la tabella contiene una colonna della chiave primaria, SingerId, che appare a sinistra della riga in grassetto e che le tabelle sono organizzate in righe e colonne.

Puoi definire la tabella con il seguente DDL:

GoogleSQL

CREATE TABLE Singers (
SingerId   INT64 NOT NULL,
FirstName  STRING(1024),
LastName   STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

PostgreSQL

CREATE TABLE singers (
singer_id   BIGINT PRIMARY KEY,
first_name  VARCHAR(1024),
last_name   VARCHAR(1024),
singer_info BYTEA
);

Tieni presente quanto segue sullo schema di esempio:

  • Singers è una tabella alla radice della gerarchia del database (in quanto non è definita come tabella secondaria con interfoliazione di un'altra tabella).
  • Per i database di dialetti GoogleSQL, in genere le colonne di chiave primaria sono annotate con NOT NULL Puoi omettere questa annotazione se vuoi consentire valori NULL in colonne chiave. Per ulteriori informazioni, consulta le sezioni Chiave colonne).
  • Le colonne non incluse nella chiave primaria sono chiamate colonne non chiave e possono avere un'annotazione facoltativa NOT NULL.
  • Le colonne che utilizzano il tipo STRING o BYTES in GoogleSQL devono essere definito con una lunghezza, che rappresenta il numero massimo di di caratteri che possono essere memorizzati nel campo. La specifica della lunghezza è facoltativo per PostgreSQL varchar e character varying di testo. Per ulteriori informazioni, consulta Tipi di dati Scalari per i database di dialetti GoogleSQL e i dati PostgreSQL tipi per database di dialetti PostgreSQL.

Qual è il layout fisico delle righe nella tabella Singers? La il seguente diagramma mostra le righe della tabella Singers archiviate dalla chiave primaria ("Singers(1)", e poi "Singers(2)", dove il numero tra parentesi è il valore della chiave primaria.

Righe di esempio di una tabella archiviata nell'ordine di chiave primaria

Il diagramma precedente mostra un esempio di confine di suddivisione tra le righe con chiave Singers(3) e Singers(4), con i dati delle suddivisioni risultanti assegnati a server diversi. Man mano che questa tabella cresce, è possibile che le righe di dati Singers vengano archiviate in posizioni diverse.

Creare tabelle principali e secondarie

Supponiamo di voler aggiungere alcuni dati di base sugli album di ogni cantante a l'applicazione musicale.

Tabella Album con cinque righe e tre colonne

Tieni presente che la chiave primaria di Albums è composta da due colonne: SingerId e AlbumId, per associare ogni album al relativo cantante. Lo schema di esempio riportato di seguito definisce le tabelle Albums e Singers nella radice della gerarchia del database, il che le rende tabelle sorelle.

-- Schema hierarchy:
-- + Singers (sibling table of Albums)
-- + Albums (sibling table of Singers)

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
SingerId     INT64 NOT NULL,
AlbumId      INT64 NOT NULL,
AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId);

PostgreSQL

CREATE TABLE singers (
singer_id   BIGINT PRIMARY KEY,
first_name  VARCHAR(1024),
last_name   VARCHAR(1024),
singer_info BYTEA
);

CREATE TABLE albums (
singer_id     BIGINT,
album_id      BIGINT,
album_title   VARCHAR,
PRIMARY KEY (singer_id, album_id)
);

Il layout fisico delle righe Singers e Albums ha l'aspetto del diagramma seguente, con le righe della tabella Albums archiviate da istanze primarie contigue quindi le righe di Singers archiviate da una chiave primaria contigua:

Layout fisico delle righe

Una nota importante sullo schema è che Spanner presuppone che non relazioni di località dei dati tra le tabelle Singers e Albums, perché si tratta di tabelle di primo livello. Man mano che il database cresce, Spanner può aggiungere confini di suddivisione tra le righe. Ciò significa che le righe della tabella Albums potrebbero finire in una suddivisione diversa rispetto alle righe della tabella Singers, e le due suddivisioni potrebbero spostarsi indipendentemente l'una dall'altra.

A seconda delle esigenze della tua applicazione, potrebbe essere opportuno consentire i dati Albums in segmenti diversi dei dati Singers. Tuttavia, ciò potrebbe comportare un calo delle prestazioni a causa della necessità di coordinare letture e aggiornamenti tra risorse distinte. Se la tua applicazione deve recuperare spesso informazioni su tutti gli album di un particolare cantante, devi creare Albums come una tabella secondaria con interleaving di Singers, che distribuisce le righe dalle due nelle tabelle di ricerca lungo la dimensione di chiave primaria. L'esempio seguente lo spiega in maggiore dettaglio.

Creare tabelle con interleaving

Una tabella con interfoliazione è una tabella che dichiari come figlia con interfoliazione di un'altra tabella perché vuoi che le righe della tabella figlio vengano memorizzate fisicamente con la riga principale associata. Come accennato in precedenza, la chiave primaria della tabella padre deve essere la prima parte della chiave primaria composita della tabella figlio.

Durante la progettazione dell'applicazione musicale, supponi di capire che l'app deve accedere spesso alle righe della tabella Albums quando accede a una riga Singers. Ad esempio, quando accedi alla riga Singers(1), devi anche accedere alle righe Albums(1, 1) e Albums(1, 2). In questo caso, Singers e Albums devono avere una relazione forte con la località dei dati. Puoi dichiarare questa relazione con le località di dati creando Albums come figlio con interleaving tabella di Singers.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)

La riga in grassetto nello schema seguente mostra come creare Albums come tabella con interleaving di Singers.

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
 ) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
 ) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

PostgreSQL

CREATE TABLE singers (
 singer_id   BIGINT PRIMARY KEY,
 first_name  VARCHAR(1024),
 last_name   VARCHAR(1024),
 singer_info BYTEA
 );

CREATE TABLE albums (
 singer_id     BIGINT,
 album_id      BIGINT,
 album_title   VARCHAR,
 PRIMARY KEY (singer_id, album_id)
 )
 INTERLEAVE IN PARENT singers ON DELETE CASCADE;

Note su questo schema:

  • SingerId, che è la prima parte della chiave primaria della tabella figlio Albums, è anche la chiave primaria della tabella padre Singers.
  • La ON DELETE CASCADE l'annotazione indica che quando viene eliminata una riga della tabella padre, vengono eliminate automaticamente anche le righe secondarie. Se una tabella secondaria non ha questa annotazione o se l'annotazione è ON DELETE NO ACTION, devi eliminare le righe secondarie prima di poter eliminare la riga principale.
  • Le righe interlacciate vengono ordinate prima in base alle righe della tabella principale, poi in base alle righe contigue della tabella figlio che condividono la chiave primaria della tabella principale. Ad esempio, "Cantanti(1)", "Album(1, 1)" e "Album(1, 2)".
  • La relazione di località dei dati di ogni cantante e dei relativi album viene conservata se questo database viene suddiviso, a condizione che le dimensioni di una riga Singers e di tutte le sue righe Albums rimangano al di sotto del limite di dimensione della suddivisione e che non esistano hotspot in nessuna di queste righe Albums.
  • La riga principale deve esistere prima di poter inserire le righe secondarie. La riga padre possono già esistere nel database o possono essere inseriti prima del delle righe figlio nella stessa transazione.

Le righe degli album sono interlacciate tra le righe dei cantanti

Crea una gerarchia di tabelle con interfoliazione

La relazione padre-figlio tra Singers e Albums può essere estesa a più tabelle discendenti. Ad esempio, potresti creare una tabella con interleaving denominato Songs come elemento secondario di Albums per memorizzare l'elenco delle tracce di ogni album:

Tabella dei brani con sei righe e quattro colonne

Songs deve avere una chiave primaria che includa tutte le chiavi primarie delle tabelle situate a un livello superiore nella gerarchia, ovvero SingerId e AlbumId.

-- Schema hierarchy:
-- + Singers
--   + Albums (interleaved table, child table of Singers)
--     + Songs (interleaved table, child table of Albums)

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
 INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE TABLE Songs (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 TrackId      INT64 NOT NULL,
 SongName     STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId, TrackId),
 INTERLEAVE IN PARENT Albums ON DELETE CASCADE;

PostgreSQL

CREATE TABLE singers (
 singer_id   BIGINT PRIMARY KEY,
 first_name  VARCHAR(1024),
 last_name   VARCHAR(1024),
 singer_info BYTEA
 );

CREATE TABLE albums (
 singer_id     BIGINT,
 album_id      BIGINT,
 album_title   VARCHAR,
 PRIMARY KEY (singer_id, album_id)
 )
 INTERLEAVE IN PARENT singers ON DELETE CASCADE;

CREATE TABLE songs (
 singer_id     BIGINT,
 album_id      BIGINT,
 track_id      BIGINT,
 song_name     VARCHAR,
 PRIMARY KEY (singer_id, album_id, track_id)
 )
 INTERLEAVE IN PARENT albums ON DELETE CASCADE;

Il seguente diagramma rappresenta una vista fisica delle righe con interleaving.

I brani sono interlacciati negli album, che sono interlacciati tra i cantanti

In questo esempio, man mano che il numero di cantanti aumenta, Spanner aggiunge la suddivisione confini tra cantanti per preservare la località di dati tra un cantante e i suoi i dati di album e brani. Tuttavia, se le dimensioni di una riga del cantante e delle relative righe figlio superano il limite di dimensioni della suddivisione o se viene rilevato un hotspot nelle righe figlio, Spanner tenta di aggiungere confini di suddivisione per isolare la riga dell'hotspot insieme a tutte le righe figlio sottostanti.

In sintesi, una tabella principale, insieme a tutte le relative tabelle figlio e discendenti, forma una gerarchia di tabelle nello schema. Sebbene ogni tabella della gerarchia sia indipendente dal punto di vista logico, interleavingle fisicamente in questo modo può migliorare le prestazioni, pre-unire efficacemente le tabelle e consentire di accedere contemporaneamente alle righe correlate riducendo al minimo gli accessi allo spazio di archiviazione.

Join con tabelle con interleaving

Se possibile, unisci i dati in tabelle con interleaving in base alla chiave primaria. Poiché ogni di solito la riga con interleaving viene archiviata fisicamente nella stessa suddivisione della riga padre Spanner può eseguire i join mediante chiave primaria localmente, riducendo al minimo accesso allo spazio di archiviazione e traffico di rete. Nell'esempio seguente, Singers e Albums sono uniti nella chiave primaria SingerId.

GoogleSQL

SELECT s.FirstName, a.AlbumTitle
FROM Singers AS s JOIN Albums AS a ON s.SingerId = a.SingerId;

PostgreSQL

SELECT s.first_name, a.album_title
FROM singers AS s JOIN albums AS a ON s.singer_id = a.singer_id;

Colonne chiave

Questa sezione include alcune note sulle colonne principali.

Modificare le chiavi delle tabelle

Le chiavi di una tabella non possono essere modificate. Non puoi aggiungere una colonna della chiave a una tabella esistente o rimuoverla da una tabella esistente.

Memorizzare valori NULL in una chiave primaria

In GoogleSQL, se vuoi memorizzare NULL in una colonna della chiave primaria, ometti la clausola NOT NULL per quella colonna nello schema. I database in dialetto PostgreSQL non supportano i valori NULL in una colonna della chiave primaria.

Ecco un esempio di omissione della clausola NOT NULL nella colonna di chiave primaria SingerId. Tieni presente che, poiché SingerId è la chiave primaria, non possono essere una riga che archivia NULL in quella colonna.

CREATE TABLE Singers (
  SingerId   INT64,
  FirstName  STRING(1024),
  LastName   STRING(1024),
) PRIMARY KEY (SingerId);

La proprietà nullable della colonna della chiave primaria deve corrispondere tra le dichiarazioni della tabella padre e della tabella figlio. In questo esempio, NOT NULL per la colonna Albums.SingerId non è consentito perché Singers.SingerId lo omette.

CREATE TABLE Singers (
  SingerId   INT64,
  FirstName  STRING(1024),
  LastName   STRING(1024),
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
  SingerId     INT64 NOT NULL,
  AlbumId      INT64 NOT NULL,
  AlbumTitle   STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
  INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Tipi non consentiti

Le seguenti colonne non possono essere di tipo ARRAY:

  • Le colonne chiave di una tabella.
  • Le colonne chiave di un indice.

Progettazione per l'architettura multi-tenancy

Ti consigliamo di implementare il multitenancy se archivi dati appartenenti a diversi clienti. Ad esempio, un servizio di musica potrebbe voler archiviare separatamente i contenuti di ogni singola casa discografica.

Multitenancy classico

Il modo classico di progettare un'architettura multi-tenancy è creare un database separato per ciascun cliente. In questo esempio, ogni database ha la propria tabella Singers:

Database 1: Ackworth Records
SingerId Nome Cognome
1MarcRiccardo
2CatalinaSmith
Database 2: Cama Records
SingerId Nome Cognome
1AliceTrentor
2GabrieleWright
Database 3: Record Eagan
SingerId Nome Cognome
1FedericoMartinez
2AnnaHarris

Multitenancy gestito dallo schema

Un altro modo per progettare in funzione della multitenancy in Spanner è avere tutti i clienti in un'unica tabella in un unico database e utilizzare un valore della chiave primaria diverso per ogni cliente. Ad esempio, potresti includere una chiave CustomerId nelle tabelle. Se imposti CustomerId come prima colonna della chiave, i dati per ogni cliente hanno una buona localizzazione. Spanner può quindi utilizzare in modo efficace le suddivisioni del database per massimizzare le prestazioni in base alle dimensioni dei dati e ai pattern di caricamento. Nell'esempio seguente, è disponibile un'unica tabella Singers per tutti i clienti:

Database multi-tenancy di Spanner
CustomerId SingerId Nome Cognome
11MarcRiccardo
12CatalinaSmith
21AliceTrentor
22GabrieleWright
31FedericoMartinez
32AnnaHarris

Se devi avere database separati per ogni tenant, tieni presente i seguenti vincoli:

  • Esistono limiti al numero di database per istanza e il numero di tabelle e indici per database. In base al numero di potrebbe non essere possibile avere database o tabelle separati.
  • L'aggiunta di nuove tabelle e indici senza interleaving può richiedere molto tempo volta. Potresti non essere in grado di ottenere il rendimento desiderato se la progettazione dello schema dipende dall'aggiunta di nuove tabelle e nuovi indici.

Se vuoi creare database separati, potresti ottenere risultati migliori se suddividi le tabelle nei database in modo che ogni database abbia un numero ridotto di modifiche dello schema a settimana.

Se crei tabelle e indici separati per ogni cliente della tua applicazione, non inserire tutte le tabelle e gli indici nello stesso database. Suddividi invece su molti database, per mitigare le prestazioni problemi con la creazione di un numero elevato di indici.

Per scoprire di più su altri pattern di gestione dei dati e sulla progettazione di applicazioni per multi-tenancy, consulta Implementazione della multitenancy in Chiave inglese