Questa pagina illustra i requisiti dello schema di Spanner, come utilizzarlo per creare relazioni gerarchiche e le funzionalità dello schema. Inoltre, introduce le tabelle con interleaving, che possono migliorare le prestazioni delle query quando si eseguono query su tabelle in una relazione padre-figlio.
Uno schema è uno spazio dei nomi che contiene oggetti di database come tabelle, viste, indici e funzioni. Puoi utilizzare gli schemi per organizzare gli oggetti, applicare privilegi di controllo dell'accesso dell'accesso granulari ed evitare collisioni di denominazione. Devi definire uno schema per ogni database in Spanner.
Puoi anche segmentare e archiviare ulteriormente le righe nella tabella di database in diverse regioni geografiche. Per ulteriori informazioni, consulta la panoramica sul partizionamento geografico.
Dati molto digitati
I dati in Spanner sono digitati con forza. I tipi di dati includono scalari e complessi, descritti in Tipi di dati in GoogleSQL e 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 chiave primaria della tabella, che identifica in modo univoco ogni riga. Le chiavi primarie sono sempre indicizzate per una ricerca rapida delle righe. Se vuoi aggiornare o eliminare righe esistenti in una tabella, la tabella deve avere una chiave primaria. Una tabella senza colonne di chiave primaria può avere una sola riga. Solo i database di dialetti GoogleSQL possono avere tabelle senza chiave primaria.
Spesso l'applicazione ha già un campo che può essere utilizzato come chiave primaria. Ad esempio, per una tabella Customers
, potrebbe essere presente un elemento CustomerId
fornito dall'applicazione che funge da chiave primaria. In altri casi, potresti dover generare una chiave primaria quando inserisci la riga. In genere, si tratta di un valore intero univoco senza significato aziendale (una chiave primaria surrogata).
In ogni caso, devi fare attenzione a non creare hotspot con la scelta della tua chiave primaria. Ad esempio, se inserisci i record con un numero intero monotonico crescente come chiave, dovrai sempre inserirli alla fine dello spazio delle chiavi. Questo è indesiderato perché Spanner divide i dati tra i server in base a intervalli di chiavi, il che significa che i tuoi inserimenti saranno indirizzati a un singolo server, creando un hotspot. Esistono tecniche in grado di distribuire il carico su più server ed evitare gli hotspot:
- Esegui l'hashing della chiave e memorizzala in una colonna. Utilizza la colonna hash (o la colonna hash insieme alle colonne delle chiavi univoche) come chiave primaria.
- Inverti l'ordine delle colonne nella chiave primaria.
- Utilizza un UUID (Universally Unique Identifier). Si consiglia la versione 4 UUID, perché utilizza valori casuali nei bit di ordine più alto. Non utilizzare un algoritmo UUID (ad esempio UUID versione 1) che memorizza il timestamp nei bit di ordine superiore.
- Esegui l'inversione dei bit.
Relazioni tabella padre-figlio
Esistono due modi per definire le relazioni padre-figlio in Spanner: interleaving delle tabelle e chiavi esterne.
L'interfoliazione delle tabelle di Spanner è una buona scelta per molte relazioni padre-figlio. Con l'interleaving, Spanner distribuisce fisicamente
le righe figlio con righe padre nello spazio di archiviazione. La colocation può migliorare
significativamente le prestazioni. Ad esempio, se hai una tabella Customers
e una
tabella Invoices
e la tua applicazione recupera spesso tutte le fatture di un
cliente, puoi definire Invoices
come tabella secondaria con interleaving di
Customers
. In questo modo dichiari una relazione di località dei dati tra due tabelle indipendenti. Stai dicendo a Spanner di archiviare una o più righe di Invoices
con una riga Customers
.
Per associare una tabella secondaria a una tabella padre, utilizza un DDL che dichiara la tabella figlio come con interleaving nella tabella padre e includi la chiave primaria della tabella padre come prima parte della chiave primaria composita della tabella figlio. Per ulteriori informazioni sull'interfoliazione, consulta la sezione Creare tabelle con interleaving più avanti in questa pagina.
Le chiavi esterne sono una soluzione padre-figlio più generale e rispondono 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 padre in alcune relazioni che come figlio in altre. Tuttavia, una relazione di chiave esterna non implica la colocation 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 entrambe. Per ulteriori informazioni sulle chiavi esterne e sul loro confronto con le tabelle con interleaving, consulta Panoramica delle chiavi esterne.
Chiavi primarie nelle tabelle con interleaving
Per l'interleaving, ogni tabella deve avere una chiave primaria. Se dichiari una tabella come secondaria con interfoliazione di un'altra tabella, la tabella deve avere una chiave primaria composita che includa tutti i componenti della chiave primaria dell'elemento padre, nello stesso ordine e, in genere, una o più colonne di tabella figlio aggiuntive.
Spanner archivia le righe in ordine ordinato in base ai valori della chiave primaria, con le righe figlio inserite tra le righe principali. Vedi un'illustrazione delle righe con interleaving in Creare tabelle con interleaving più avanti in questa pagina.
In sintesi, Spanner può collocare fisicamente righe di tabelle correlate. Gli esempi di schema mostrano l'aspetto di questo layout fisico.
Suddivisione del database
È possibile definire le gerarchie di relazioni padre-figlio con interfoliazione fino a sette livelli, il che significa che è possibile collocare righe di sette tabelle indipendenti. Se le dimensioni dei dati nelle tabelle sono ridotte, è probabile che il database possa essere gestito da un singolo server Spanner. Ma cosa succede quando le tabelle correlate crescono e iniziano a raggiungere i limiti delle risorse di un singolo server? Spanner è un database distribuito, il che significa che man mano che il database cresce, Spanner suddivide i dati in blocchi denominati "split". I singoli segmenti possono essere spostati in modo indipendente l'uno dall'altro e vengono assegnati a server diversi, che possono trovarsi in posizioni fisiche diverse. Una suddivisione contiene un intervallo di righe contigue. Le chiavi iniziale e finale di questo intervallo sono chiamate "confini della suddivisionee". Spanner aggiunge e rimuove automaticamente iconfini della suddivisionei in base alle dimensioni e al carico, cambiando il numero di suddivisioni nel database.
Suddivisione basata sul carico
Per un esempio di come Spanner esegue la suddivisione basata sul carico per mitigare gli hotspot di lettura, supponiamo che il database contenga una tabella con 10 righe che vengono lette più spesso di tutte le altre righe della tabella. Spanner può aggiungere confini della suddivisione tra ciascuna di queste 10 righe in modo che ciascuna sia gestita da un server diverso, invece di 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 migliori a intervalli di pochi minuti fino a quando non saturano le risorse nell'istanza o riscontri casi in cui non è possibile aggiungere nuovi confini della suddivisione (perché hai una suddivisione che copre solo una singola riga senza elementi figlio interleali).
Schemi denominati
Gli schemi denominati consentono di organizzare insieme dati simili. In questo modo puoi trovare rapidamente oggetti nella console Google Cloud, applicare privilegi ed evitare collisioni di nomi.
Gli schemi con nome, come altri oggetti di database, vengono gestiti utilizzando DDL.
Gli schemi denominati di Spanner consentono di utilizzare nomi completi
(FQN) per eseguire query sui dati. Consentono di combinare il nome dello schema e il nome dell'oggetto per identificare gli oggetti del database. Ad esempio, potresti creare uno schema denominato warehouse
per l'unità aziendale del warehouse. Le tabelle che utilizzano questo
schema potrebbero includere: product
, order
e customer information
. In alternativa,
puoi creare uno schema denominato fulfillment
per l'unità aziendale 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
, mentre nel secondo è fulfillment.product
. In questo modo si evita di fare confusione
nelle situazioni in cui più oggetti condividono lo stesso nome.
Nel DDL CREATE SCHEMA
, agli oggetti della tabella viene assegnato sia un nome di dominio completo, ad esempio sales.customers
, sia un nome breve, ad esempio sales
.
I seguenti oggetti di 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 controllo dell'accesso granulare con schemi denominati
Gli schemi con nome consentono di concedere l'accesso a livello di schema a ciascun oggetto nello schema. Questo vale per gli oggetti dello schema esistenti al momento della concessione dell'accesso. Devi concedere l'accesso agli oggetti aggiunti in un secondo momento.
Controllo dell'accesso granulare limita l'accesso a interi gruppi di oggetti di database, come tabelle, colonne e righe nella tabella.
Per ulteriori informazioni, consulta l'articolo Concedere privilegi di controllo dell'accesso granulari per gli schemi denominati.
Esempi di schema
Gli esempi di schema in questa sezione mostrano come creare tabelle padre e figlio con e senza interfoliazione e illustrano i layout fisici corrispondenti dei dati.
Crea una tabella padre
Supponiamo che tu stia creando un'applicazione di musica e di aver bisogno di una tabella per archiviare righe di dati sui cantieri:
Tieni presente che la tabella contiene una colonna di chiave primaria, SingerId
, che appare a sinistra della riga in grassetto, e che le tabelle sono organizzate per 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 in merito allo schema di esempio:
Singers
è una tabella all'inizio della gerarchia del database (perché non è definita come elemento figlio con interfoliazione di un'altra tabella).- Per i database di dialetti GoogleSQL, le colonne di chiave primaria sono in genere annotate con
NOT NULL
ma puoi omettere questa annotazione se vuoi consentire i valoriNULL
nelle colonne delle chiavi. Per maggiori informazioni, consulta la sezione Colonne chiave. - Le colonne che non sono incluse nella chiave primaria sono chiamate colonne non chiave e possono avere un'annotazione
NOT NULL
facoltativa. - Le colonne che utilizzano il tipo
STRING
oBYTES
in GoogleSQL devono essere definite con una lunghezza, che rappresenta il numero massimo di caratteri Unicode che possono essere archiviati nel campo. La specifica della lunghezza è facoltativa per i tipi PostgreSQLvarchar
echaracter varying
. Per ulteriori informazioni, consulta Scalar Data Types per i database di dialetti GoogleSQL e Tipi di dati PostgreSQL per i database con dialetti PostgreSQL.
Qual è il layout fisico delle righe nella tabella Singers
? Il seguente diagramma mostra le righe della tabella Singers
archiviate dalla chiave primaria ("Singers(1)", poi "Singers(2)", dove il numero tra parentesi è il valore della chiave primaria.
Il diagramma precedente illustra un esempio di confine di suddivisione tra le righe
associate a Singers(3)
e Singers(4)
, con i dati delle suddivisioni risultanti
assegnati a server diversi. Man mano che la tabella cresce, è possibile che le righe di
dati Singers
vengano archiviate in località diverse.
Creare tabelle padre e figlio
Supponi di voler aggiungere all'applicazione musicale alcuni dati di base sugli album di ogni cantante.
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 seguente definisce entrambe le tabelle Albums
e Singers
alla radice della gerarchia del database, il che le rende tabelle di pari livello.
-- 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
è simile al diagramma seguente, con le righe della tabella Albums
archiviate da una chiave primaria contigua, poi le righe di Singers
archiviate da una chiave primaria contigua:
Una nota importante sullo schema è che Spanner non presuppone alcuna relazione di località dei dati tra le tabelle Singers
e Albums
, poiché si tratta di tabelle di primo livello. Man mano che il database cresce, Spanner può
aggiungereconfini della suddivisionei tra qualsiasi riga. Ciò significa che le righe della tabella Albums
potrebbero terminare in una suddivisione diversa dalle righe della tabella Singers
e le due suddivisioni potrebbero muoversi in modo indipendente l'una dall'altra.
A seconda delle esigenze dell'applicazione, potrebbe essere opportuno consentire la posizione dei dati Albums
su suddivisioni diverse dai dati Singers
. Tuttavia, in questo caso potresti incorrere in
una riduzione delle prestazioni dovuta alla necessità di coordinare le letture e gli aggiornamenti
tra risorse distinte. Se l'applicazione deve recuperare spesso informazioni su tutti gli album di un determinato cantante, devi creare Albums
come tabella secondaria con interleaving di Singers
, che colloca le righe delle due tabelle lungo la dimensione della chiave primaria. L'esempio seguente spiega
più in dettaglio.
Creare tabelle con interleaving
Una tabella con interleaving è una tabella che dichiari come elemento figlio con interleaving di un'altra tabella perché vuoi che le righe della tabella figlio siano archiviate fisicamente con la riga padre associata. Come già detto, la chiave primaria della tabella padre deve essere la prima parte della chiave primaria composita della tabella figlio.
Durante la progettazione della tua applicazione musicale, supponi di renderti conto che l'app
deve accedere frequentemente alle righe della tabella Albums
quando accede a una
riga Singers
. Ad esempio, quando accedi alla riga Singers(1)
, devi accedere anche alle righe Albums(1, 1)
e Albums(1, 2)
. In questo caso, Singers
e Albums
devono avere una relazione forte tra le località dei dati. Puoi dichiarare
questa relazione di località dei dati creando Albums
come tabella secondaria con interleaving
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 figlioAlbums
, è anche la chiave primaria della relativa tabella padreSingers
.- L'annotazione
ON DELETE CASCADE
indica che quando viene eliminata una riga della tabella padre, vengono eliminate automaticamente anche le relative righe secondarie. Se una tabella secondaria non ha questa annotazione o l'annotazione èON DELETE NO ACTION
, devi eliminare le righe figlio prima di poter eliminare la riga padre. - Le righe con interleaving vengono ordinate prima in base alle righe della tabella padre, poi in base alle righe contigue della tabella figlio che condividono la chiave primaria dell'elemento padre. Ad esempio, "Cantanti(1)", poi "Album(1, 1)" e infine "Album(1, 2)".
- La relazione di località dei dati di ogni cantante e i dati dei relativi album viene
conservata se il database si divide, purché la dimensione di una riga
Singers
e tutte le sue righeAlbums
rimangano al di sotto del limite di dimensione suddiviso e che non sia presente alcun hotspot in nessuna di queste righe (Albums
). - La riga principale deve esistere prima di poter inserire righe figlio. La riga padre può già esistere nel database o può essere inserita prima dell'inserimento delle righe figlio nella stessa transazione.
Creare una gerarchia di tabelle con interleaving
La relazione padre-figlio tra Singers
e Albums
può essere estesa a
più tabelle discendenti. Ad esempio, puoi creare una tabella con interleaving denominata Songs
come elemento secondario di Albums
per archiviare l'elenco delle tracce di ogni album:
Songs
deve avere una chiave primaria che includa tutte le chiavi primarie delle tabelle 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.
In questo esempio, man mano che il numero di cantanti aumenta, Spanner aggiunge confini divisi tra i cantanti per preservare la località dei dati tra un cantante e i dati dell'album e del brano. Tuttavia, se le dimensioni di una riga cantante e delle relative righe figlio superano il limite di dimensioni divise o se viene rilevato un hotspot nelle righe figlio, Spanner tenta di aggiungere confini della suddivisione per isolare la riga dell'hotspot insieme a tutte le righe figlio sotto di essa.
In sintesi, una tabella padre, insieme a tutte le tabelle figlio e discendenti, forma una gerarchia di tabelle nello schema. Sebbene ogni tabella nella gerarchia sia indipendente da un punto di vista logico, l'interlesione fisica in questo modo può migliorare le prestazioni, eseguendo efficacemente il pre-unione delle tabelle e consentendo di accedere insieme 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 riga con interleaving solitamente viene archiviata fisicamente nella stessa suddivisione della riga padre, Spanner può eseguire localmente i join mediante chiave primaria, riducendo al minimo l'accesso allo spazio di archiviazione e il 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 chiave.
Modifica chiavi tabella
Le chiavi di una tabella non possono essere modificate. Non puoi aggiungere una colonna chiave a una tabella esistente o rimuovere una colonna chiave da una tabella esistente.
Archivia i valori NULL in una chiave primaria
In GoogleSQL, se vuoi archiviare NULL in una colonna di chiave primaria, ometti la clausola NOT NULL
per quella colonna nello schema. I database di dialetti PostgreSQL non supportano
i valori NULL in una colonna di 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, può esserci solo una riga che archivia NULL
in quella colonna.
CREATE TABLE Singers ( SingerId INT64, FirstName STRING(1024), LastName STRING(1024), ) PRIMARY KEY (SingerId);
La proprietà null della colonna di chiave primaria deve corrispondere tra le dichiarazioni della tabella padre e quelle secondarie. 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
Potresti voler implementare la multitenancy se archivi dati che appartengono a clienti diversi. Ad esempio, un servizio musicale potrebbe voler archiviare i contenuti di ogni singola casa discografica.
Multitenancy classica
Il modo classico di progettare un'architettura multi-tenancy è creare un database separato per ogni cliente. In questo esempio, ogni database ha la propria tabella Singers
:
SingerId | FirstName | LastName |
---|---|---|
1 | Marco | Riccardo |
2 | Catalina | Smith |
SingerId | FirstName | LastName |
---|---|---|
1 | Alice | Trento |
2 | Gabriele | Wright |
SingerId | FirstName | LastName |
---|---|---|
1 | Federico | Martinez |
2 | Anna | Harris |
Multitenancy gestita da schema
Un altro modo di progettare l'architettura multi-tenancy in Spanner è avere tutti i clienti in una singola tabella in un unico database e utilizzare un valore chiave primaria diverso per ogni cliente. Ad esempio, puoi includere nelle tabelle una colonna chiave
CustomerId
. Se imposti CustomerId
come prima colonna chiave, i dati per ogni cliente hanno una località corretta. Spanner può quindi utilizzare in modo efficace le suddivisioni del database per massimizzare le prestazioni in base alla dimensione dei dati e ai pattern di caricamento. Nell'esempio seguente,
è presente una singola tabella Singers
per tutti i clienti:
CustomerId | SingerId | FirstName | LastName |
---|---|---|---|
1 | 1 | Marco | Riccardo |
1 | 2 | Catalina | Smith |
2 | 1 | Alice | Trento |
2 | 2 | Gabriele | Wright |
3 | 1 | Federico | Martinez |
3 | 2 | Anna | Harris |
Se devi avere database separati per ogni tenant, devi tenere presente i seguenti vincoli:
- Esistono limiti al numero di database per istanza e al numero di tabelle e indici per database. A seconda del numero di clienti, potrebbe non essere possibile avere database o tabelle separati.
- L'aggiunta di nuove tabelle e indici senza interleaving può richiedere molto tempo. Potresti non essere in grado di ottenere le prestazioni desiderate se la progettazione dello schema dipende dall'aggiunta di nuove tabelle e nuovi indici.
Se vuoi creare database separati, potresti avere più successo se distribuisci le tabelle tra i database in modo che ogni database abbia un basso numero di modifiche allo schema ogni settimana.
Se crei tabelle e indici separati per ciascun cliente della tua applicazione, non inserire tutte le tabelle e gli indici nello stesso database. Puoi invece dividerli tra più database per mitigare i problemi di prestazioni causati dalla creazione di un numero elevato di indici.
Per scoprire di più su altri pattern di gestione dei dati e sulla progettazione di applicazioni per l'architettura multi-tenancy, consulta Implementazione della multitenancy in Spanner