Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Anche se i database senza schema, come Azure Cosmos DB, semplificano l'archiviazione e l'esecuzione di query su dati non strutturati e semistrutturati, considerare il modello di dati per ottimizzare prestazioni, scalabilità e costi.
Come vengono archiviati i dati? In che modo l'applicazione recupera ed esegue query sui dati? L'applicazione richiede molte letture o molte scritture?
Dopo aver letto questo articolo, è possibile rispondere alle domande seguenti:
- Cos'è la modellazione dei dati e perché è importante?
- In che modo la modellazione dei dati in Azure Cosmos DB è diversa da un database relazionale?
- Come si esprimono le relazioni tra dati in un database non relazionale?
- Quando si incorporano i dati e quando si creano i collegamenti ai dati?
Numeri in JSON
Azure Cosmos DB salva i documenti in JSON, quindi è importante determinare se convertire i numeri in stringhe prima di archiviarli in JSON. Convertire tutti i numeri in una String se potrebbero superare i limiti dei numeri a precisione doppia come definito dall'Institute of Electrical and Electronics Engineers (IEEE) 754 binary64. La specifica JSON spiega perché l'uso di numeri al di fuori di questo limite è una procedura non valida a causa di problemi di interoperabilità. Questi problemi sono particolarmente rilevanti per la colonna chiave della partizione, poiché è invariabile e richiede la migrazione dei dati per la modifica in un secondo momento.
Incorporare dati
Quando si modellano i dati in Azure Cosmos DB, considerare le entità come elementi autonomi rappresentati come documenti JSON.
Per un confronto, si veda innanzitutto come modellare i dati in un database relazionale. L'esempio seguente mostra come una persona possa essere archiviata in un database relazionale.
La strategia, quando si usano i database relazionali, consiste nel normalizzare tutti i dati. La normalizzazione dei dati implica di solito la suddivisione di un'entità, ad esempio una persona, in componenti discreti. Nell'esempio, una persona può avere più record di dettagli di contatto e più record di indirizzi. È possibile suddividere ulteriormente i dettagli dei contatti estraendo campi comuni, ad esempio il tipo. Lo stesso approccio si applica agli indirizzi. Ogni record può essere classificato come Home o Business.
La premessa guida per la normalizzazione dei dati consiste nell'evitare di archiviare dati ridondanti in ogni record e fare invece riferimento ai dati. In questo esempio, per leggere una persona, con tutti i dettagli di contatto e gli indirizzi, è necessario usare i join per ricomporre (o denormalizzare) in modo efficace i dati in fase di esecuzione.
SELECT p.FirstName, p.LastName, a.City, cd.Detail
FROM Person p
JOIN ContactDetail cd ON cd.PersonId = p.Id
JOIN ContactDetailType cdt ON cdt.Id = cd.TypeId
JOIN Address a ON a.PersonId = p.Id
L'aggiornamento dei dettagli di contatto e degli indirizzi di una singola persona richiede operazioni di scrittura in molte singole tabelle.
Ora si esaminerà come si modellano gli stessi dati come entità autonoma in Azure Cosmos DB.
{
"id": "1",
"firstName": "Thomas",
"lastName": "Andersen",
"addresses": [
{
"line1": "100 Some Street",
"line2": "Unit 1",
"city": "Seattle",
"state": "WA",
"zip": 98012
}
],
"contactDetails": [
{"email": "thomas@andersen.com"},
{"phone": "+1 555 555-5555", "extension": 5555}
]
}
Usando questo approccio, il record della persona è stato denormalizzatoincorporando tutte le informazioni correlate a questa persona, ad esempio i dettagli di contatto e gli indirizzi, in un singolo documento JSON. Inoltre, dal momento che non esistono limiti imposti da uno schema fisso, abbiamo la flessibilità necessaria, ad esempio, per avere dettagli dei contatti che hanno forme completamente diverse.
Il recupero del record completo di una persona dal database ora è una singola operazione di lettura su un singolo contenitore per un singolo elemento. Anche l'aggiornamento dei dettagli di contatto e degli indirizzi del record di una persona richiede una sola operazione di scrittura in un solo elemento.
La denormalizzazione dei dati potrebbe ridurre il numero di query e gli aggiornamenti necessari all'applicazione per completare operazioni comuni.
Quando eseguire l'incorporamento
In generale, usare i modelli di dati incorporati quando:
- Esistono relazioni indipendenti tra le entità.
- Esistono relazioni one-to-few tra le entità.
- I dati cambiano raramente.
- I dati non aumentano senza limiti.
- I dati vengono sottoposti spesso a query insieme.
Nota
I modelli di dati denormalizzati garantiscono di solito prestazioni di lettura più elevate.
Quando non eseguire l'incorporamento
Anche se la regola generale in Azure Cosmos DB consiste nel denormalizzare tutti gli elementi e incorporare tutti i dati in un singolo elemento, questo approccio può causare situazioni da evitare.
Consideriamo questo frammento JSON.
{
"id": "1",
"name": "What's new in the coolest Cloud",
"summary": "A blog post by someone real famous",
"comments": [
{"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
{"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
…
{"id": 100001, "author": "jane", "comment": "and on we go ..."},
…
{"id": 1000000001, "author": "angry", "comment": "blah angry blah angry"},
…
{"id": ∞ + 1, "author": "bored", "comment": "oh man, will this ever end?"},
]
}
Questo esempio potrebbe essere l'aspetto di un'entità post con commenti incorporati se si stesse modellando un tipico blog o un sistema di gestione dei contenuti (CMS). Il problema di questo esempio è che la matrice di commenti non è limitata, vale a dire che non esiste in pratica un limite al numero di commenti per ogni singolo post. Questa progettazione può causare problemi perché le dimensioni dell'elemento possono crescere infinitamente, per cui è opportuno evitarla.
Man mano che le dimensioni dell'elemento aumentano, la trasmissione, la lettura e l'aggiornamento dei dati su larga scala diventano più difficili.
In questo caso, è meglio prendere in considerazione il modello di dati seguente.
Post item:
{
"id": "1",
"name": "What's new in the coolest Cloud",
"summary": "A blog post by someone real famous",
"recentComments": [
{"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
{"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
{"id": 3, "author": "jane", "comment": "....."}
]
}
Comment items:
[
{"id": 4, "postId": "1", "author": "anon", "comment": "more goodness"},
{"id": 5, "postId": "1", "author": "bob", "comment": "tails from the field"},
...
{"id": 99, "postId": "1", "author": "angry", "comment": "blah angry blah angry"},
{"id": 100, "postId": "2", "author": "anon", "comment": "yet more"},
...
{"id": 199, "postId": "2", "author": "bored", "comment": "will this ever end?"}
]
Questo modello ha un elemento per ogni commento con una proprietà che contiene l'identificatore di post. Questo modello consente ai post di contenere un numero qualsiasi di commenti e crescere in modo efficiente. Gli utenti che non vogliono visualizzare solo i commenti più recenti devono eseguire una query su questo contenitore passando postId, che deve essere la chiave di partizione per il contenitore dei commenti.
Un altro caso in cui l'incorporamento dei dati è sconsigliabile è quando i dati incorporati vengono usati spesso tra elementi e modifiche frequenti.
Consideriamo questo frammento JSON.
{
"id": "1",
"firstName": "Thomas",
"lastName": "Andersen",
"holdings": [
{
"numberHeld": 100,
"stock": { "symbol": "zbzb", "open": 1, "high": 2, "low": 0.5 }
},
{
"numberHeld": 50,
"stock": { "symbol": "xcxc", "open": 89, "high": 93.24, "low": 88.87 }
}
]
}
Questo esempio potrebbe rappresentare il portafoglio azionario di una persona. Abbiamo scelto di incorporare le informazioni sulle azioni in ogni documento del portfolio. In un ambiente in cui i dati correlati cambiano frequentemente incorporando dati che cambiano frequentemente significa che si sta aggiornando costantemente ogni portfolio. Usando un esempio di applicazione di trading azionario, si sta aggiornando ogni elemento portafoglio ogni volta che viene scambiato un titolo.
Le azioni zbzb possono essere scambiate centinaia di volte in un singolo giorno e migliaia di utenti potrebbero avere zbzb nei loro portafogli. Con un modello di dati come l'esempio, il sistema deve aggiornare migliaia di documenti del portfolio molte volte al giorno, che non si ridimensiona correttamente.
Dati di riferimento
L'incorporamento dei dati è adatto in molti casi, ma esistono scenari in cui la denormalizzazione dei dati causa più problemi di quanti ne risolve. Allora cosa si può fare?
È possibile creare relazioni tra entità nei database di documenti, non solo nei database relazionali. In un database di documenti, un elemento può includere informazioni che si connettono ai dati in altri documenti. Azure Cosmos DB non è progettato per relazioni complesse come quelle nei database relazionali, ma i collegamenti semplici tra gli elementi sono possibili e possono essere utili.
In JSON viene usato l'esempio di un portafoglio azionario precedente, ma questa volta si fa riferimento all'elemento titolo nel portfolio invece di incorporarlo. In questo modo, quando l'elemento titolo cambia frequentemente durante tutto il giorno, l'unico elemento che deve essere aggiornato è il singolo documento dell'elemento titolo.
Person document:
{
"id": "1",
"firstName": "Thomas",
"lastName": "Andersen",
"holdings": [
{ "numberHeld": 100, "stockId": 1},
{ "numberHeld": 50, "stockId": 2}
]
}
Stock documents:
{
"id": "1",
"symbol": "zbzb",
"open": 1,
"high": 2,
"low": 0.5,
"vol": 11970000,
"mkt-cap": 42000000,
"pe": 5.89
},
{
"id": "2",
"symbol": "xcxc",
"open": 89,
"high": 93.24,
"low": 88.87,
"vol": 2970200,
"mkt-cap": 1005000,
"pe": 75.82
}
Uno svantaggio di questo approccio è che l'applicazione deve effettuare diverse richieste di database per ottenere informazioni su ogni titolo nel portfolio di una persona. Questa progettazione rende più veloce la scrittura dei dati, poiché gli aggiornamenti vengono eseguiti spesso. Tuttavia, rallenta la lettura o l'esecuzione di query sui dati, che è meno importante per questo sistema.
Nota
I modelli di dati normalizzati possono richiedere più viaggi di andata e ritorno al server.
Che ne dici delle chiavi esterne?
Poiché non esiste alcun concetto di vincolo, ad esempio una chiave esterna, il database non verifica alcuna relazione tra documenti nei documenti; questi collegamenti sono effettivamente "deboli". Se si vuole assicurarsi che i dati a cui fa riferimento un elemento in realtà esistano, è necessario eseguire questo passaggio nell'applicazione o usando trigger lato server o stored procedure in Azure Cosmos DB.
Quando fare riferimento
In generale, usare i modelli di dati normalizzati quando:
- Rappresentazione di relazioni uno a molti.
- Rappresentazione di relazioni molti a molti.
- I dati correlati cambiano spesso.
- I dati di riferimento potrebbero essere non limitati.
Nota
La normalizzazione offre di solito migliori prestazioni di scrittura .
Dove metto la relazione?
La crescita della relazione consente di determinare in quale elemento archiviare il riferimento.
Se osserviamo il codice JSON che modella editori e libri.
Publisher document:
{
"id": "mspress",
"name": "Microsoft Press",
"books": [ 1, 2, 3, ..., 100, ..., 1000]
}
Book documents:
{"id": "1", "name": "Azure Cosmos DB 101" }
{"id": "2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "3", "name": "Taking over the world one JSON doc at a time" }
...
{"id": "100", "name": "Learn about Azure Cosmos DB" }
...
{"id": "1000", "name": "Deep Dive into Azure Cosmos DB" }
Se il numero di libri per editore è ridotto e la crescita è limitata, l'archiviazione del riferimento al libro all'interno dell'elemento editore potrebbe risultare utile. Se invece il numero di libri per editore è illimitato, questo modello di dati darà origine a matrici modificabili e in costante crescita, come nel documento dell'editore di esempio.
Se si cambia struttura, viene restituito un modello che rappresenta gli stessi dati, ma evita raccolte mutevoli di grandi dimensioni.
Publisher document:
{
"id": "mspress",
"name": "Microsoft Press"
}
Book documents:
{"id": "1","name": "Azure Cosmos DB 101", "pub-id": "mspress"}
{"id": "2","name": "Azure Cosmos DB for RDBMS Users", "pub-id": "mspress"}
{"id": "3","name": "Taking over the world one JSON doc at a time", "pub-id": "mspress"}
...
{"id": "100","name": "Learn about Azure Cosmos DB", "pub-id": "mspress"}
...
{"id": "1000","name": "Deep Dive into Azure Cosmos DB", "pub-id": "mspress"}
In questo esempio, il documento dell'editore non contiene più una raccolta non associata. Ogni documento include invece un riferimento al relativo editore.
Come modellare relazioni molti-a-molti?
In un database relazionale le relazioni molti-a-molti vengono spesso modellate con tabelle di unione. Queste relazioni uniscono semplicemente i record di altre tabelle.
Si potrebbe essere tentati di replicare la stessa cosa con i documenti e di generare un modello di dati simile al seguente.
Author documents:
{"id": "a1", "name": "Thomas Andersen" }
{"id": "a2", "name": "William Wakefield" }
Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101" }
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "b3", "name": "Taking over the world one JSON doc at a time" }
{"id": "b4", "name": "Learn about Azure Cosmos DB" }
{"id": "b5", "name": "Deep Dive into Azure Cosmos DB" }
Joining documents:
{"authorId": "a1", "bookId": "b1" }
{"authorId": "a2", "bookId": "b1" }
{"authorId": "a1", "bookId": "b2" }
{"authorId": "a1", "bookId": "b3" }
Questo approccio funziona, ma il caricamento di un autore con suoi i libri o un libro con il suo autore richiede sempre almeno due query di database aggiuntive. Una query sull'elemento di unione e quindi un'altra query per recuperare l'elemento effettivo unito.
Se il join si limita a incollare insieme due parti di dati, allora perché non eliminarlo del tutto? Si consideri l'esempio seguente.
Author documents:
{"id": "a1", "name": "Thomas Andersen", "books": ["b1", "b2", "b3"]}
{"id": "a2", "name": "William Wakefield", "books": ["b1", "b4"]}
Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101", "authors": ["a1", "a2"]}
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users", "authors": ["a1"]}
{"id": "b3", "name": "Learn about Azure Cosmos DB", "authors": ["a1"]}
{"id": "b4", "name": "Deep Dive into Azure Cosmos DB", "authors": ["a2"]}
Con questo modello, è possibile vedere facilmente quali libri un autore ha scritto esaminando il relativo documento. È anche possibile vedere quali autori hanno scritto un libro controllando il documento del libro. Non è necessario usare una tabella di unione separata o eseguire query aggiuntive. Questo modello rende più veloce e semplice per l'applicazione ottenere i dati necessari.
Modelli di dati ibridi
Vengono esaminati l'incorporamento (o la denormalizzazione) e i dati di riferimento (o normalizzazione). Ogni approccio offre vantaggi e comporta compromessi.
Non deve sempre essere o-o. Non esitare a mescolare un po' le cose.
In base ai modelli di utilizzo e ai carichi di lavoro specifici dell'applicazione, la combinazione di dati incorporati e a cui si fa riferimento potrebbe avere senso. Questo approccio potrebbe semplificare la logica dell'applicazione, ridurre i round trip del server e mantenere prestazioni ottimali.
Si consideri il codice JSON seguente.
Author documents:
{
"id": "a1",
"firstName": "Thomas",
"lastName": "Andersen",
"countOfBooks": 3,
"books": ["b1", "b2", "b3"],
"images": [
{"thumbnail": "https://....png"}
{"profile": "https://....png"}
{"large": "https://....png"}
]
},
{
"id": "a2",
"firstName": "William",
"lastName": "Wakefield",
"countOfBooks": 1,
"books": ["b1"],
"images": [
{"thumbnail": "https://....png"}
]
}
Book documents:
{
"id": "b1",
"name": "Azure Cosmos DB 101",
"authors": [
{"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
{"id": "a2", "name": "William Wakefield", "thumbnailUrl": "https://....png"}
]
},
{
"id": "b2",
"name": "Azure Cosmos DB for RDBMS Users",
"authors": [
{"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
]
}
In questo caso è stato seguito (principalmente) il modello incorporato, in cui i dati di altre entità sono incorporati nel documento di primo livello, ma viene fatto riferimento ad altri dati.
Se si osserva il documento dei libri, si possono vedere alcuni campi interessanti quando si considera la matrice degli autori. È presente un campo id che viene usato per fare riferimento al documento di un autore (procedura standard in un modello normalizzato), ma sono presenti anche i campi name e thumbnailUrl. È possibile usare solo e id consentire all'applicazione di recuperare eventuali informazioni aggiuntive necessarie dall'elemento autore corrispondente usando il "collegamento". Tuttavia, poiché l'applicazione visualizza il nome dell'autore e un'immagine di anteprima con ogni libro, la denormalizzazione di alcuni dati dell'autore riduce il numero di round trip del server per libro in un elenco.
Se il nome dell'autore cambia o aggiorna la foto, è necessario aggiornare ogni libro pubblicato. Tuttavia, per questa applicazione, supponendo che gli autori cambino raramente i nomi, questo compromesso costituisce una decisione di progettazione accettabile.
Nell'esempio, esistono valori aggregati precalcolati per risparmiare un'elaborazione costosa durante un'operazione di lettura. Nell'esempio, alcuni dati incorporati nell'elemento autore sono dati calcolati in fase di esecuzione. Ogni volta che viene pubblicato un nuovo libro, viene creato un elemento libro e il campo countOfBooks viene impostato su un valore calcolato in base al numero di documenti libro esistenti per un particolare autore. Questa ottimizzazione andrebbe bene nei sistemi che eseguono un'intensa attività di lettura, in cui si è disposti a effettuare calcoli nelle scritture per ottimizzare le letture.
La possibilità di avere un modello con campi precalcolati è resa possibile perché Azure Cosmos DB supporta le transazioni su più documenti. Molti archivi NoSQL non possono eseguire transazioni tra documenti e quindi avallano decisioni di progettazione come "incorporare sempre tutto" a causa di questa limitazione. Con Azure Cosmos DB è possibile usare trigger lato server o stored procedure che inseriscono libri e aggiornano autori in una sola transazione ACID. A questo punto non è necessario incorporare tutto in un solo elemento per assicurarsi che i dati rimangano coerenti.
Distinguere tra tipi di elemento diversi
In alcuni scenari potrebbe essere opportuno mescolare tipi di elementi diversi nella stessa raccolta; questa scelta di progettazione è in genere il caso in cui si desidera che più documenti correlati si trovino nella stessa partizione. Ad esempio, è possibile inserire sia i libri che le relative recensioni nella stessa raccolta e partizionarla per bookId. In una situazione di questo tipo, in genere si vuole aggiungere un campo ai documenti che ne identificano il tipo per differenziarli.
Book documents:
{
"id": "b1",
"name": "Azure Cosmos DB 101",
"bookId": "b1",
"type": "book"
}
Review documents:
{
"id": "r1",
"content": "This book is awesome",
"bookId": "b1",
"type": "review"
}
{
"id": "r2",
"content": "Best book ever!",
"bookId": "b1",
"type": "review"
}
Modellazione dei dati per Azure Synapse Link e store analitico di Azure Cosmos DB
Collegamento ad Azure Synapse per Azure Cosmos DB è una funzionalità HTAP (Hybrid Transactional and Analytical Processing) nativa del cloud che consente di eseguire analisi in modalità near real-time su dati operativi in Azure Cosmos DB. Collegamento ad Azure Synapse crea un'integrazione perfetta tra Azure Cosmos DB e Azure Synapse Analytics.
Questa integrazione avviene tramite l'archivio analitico di Azure Cosmos DB, una rappresentazione a colonne dei dati transazionali che consente l'analisi su larga scala senza alcun effetto sui carichi di lavoro transazionali. L'archivio analitico consente di eseguire query rapide e convenienti su grandi set di dati. Non è necessario copiare i dati o preoccuparsi del rallentamento del database principale. Quando si attiva l'archivio analitico per un contenitore, ogni modifica apportata ai dati viene copiata nell'archivio analitico quasi immediatamente. Non è necessario configurare feed di modifiche o eseguire processi di estrazione, trasformazione e caricamento (ETL). Il sistema mantiene sincronizzati entrambi gli archivi.
Con Collegamento ad Azure Synapse ora è possibile connettersi direttamente ai contenitori di Azure Cosmos DB da Azure Synapse Analytics e accedere all'archivio analitico senza usare unità richiesta. Azure Synapse Analytics attualmente supporta Collegamento ad Azure Synapse con i pool Apache Spark per Synapse e i pool SQL serverless. Se si ha un account Azure Cosmos DB distribuito a livello globale, un archivio analitico abilitato per un contenitore sarà disponibile in tutte le aree per tale account.
Inferenza automatica dello schema dell'archivio analitico
L'archivio transazionale di Azure Cosmos DB è costituito da dati semistrutturati orientati alle righe, mentre l'archivio analitico usa un formato a colonne e strutturato. Questa conversione viene eseguita automaticamente per i clienti, usando le regole di inferenza dello schema per l'archivio analitico. Il processo di conversione ha dei limiti: numero massimo di livelli annidati, numero massimo di proprietà, tipi di dati non supportati e altro ancora.
Nota
Nel contesto dell'archivio analitico le strutture seguenti vengono considerate come proprietà:
- "Elementi" JSON o "coppie stringa-valore separate da
:" - Oggetti JSON delimitati da
{e} - Array JSON delimitati da
[e]
È possibile ridurre al minimo l'effetto delle conversioni di inferenza dello schema e ottimizzare le funzionalità analitiche usando le tecniche seguenti.
Normalizzazione
La normalizzazione diventa meno rilevante perché Collegamento ad Azure Synapse consente di unire contenitori usando T-SQL o Spark SQL. I vantaggi previsti della normalizzazione sono:
- Riduzione dell'ingombro dei dati nella memorizzazione transazionale e analitica.
- Transazioni più piccole.
- Numero inferiore di proprietà per documento.
- Strutture di dati con un numero inferiori di livelli annidati.
Avere un minor numero di proprietà e livelli nei dati accelera le query analitiche. Consente anche di assicurarsi che tutte le parti dei dati siano incluse nell'archivio analitico. Come descritto nell'articolo sulle regole di inferenza automatica dello schema, c'è un limite al numero di livelli e proprietà che sono rappresentati nell'archivio analitico.
Un altro fattore importante per la normalizzazione è che i pool SQL serverless in Azure Synapse supportano i set di risultati con un massimo di 1.000 colonne e anche l'esposizione di colonne annidate viene conteggiata per tale limite. In altre parole, sia l'archivio analitico che i pool serverless di Synapse SQL hanno un limite di 1.000 proprietà.
Ma cosa fare considerato che la denormalizzazione è una tecnica di modellazione dei dati importante per Azure Cosmos DB? La risposta è che è necessario trovare il giusto equilibrio per i carichi di lavoro transazionali e analitici.
Chiave di partizione
La chiave di partizione (PK) di Azure Cosmos DB non viene usata nell'archivio analitico. È ora possibile usare il partizionamento personalizzato dell'archivio analitico per creare copie dell'archivio analitico utilizzando la chiave di partizione che preferisci. A causa di questo isolamento, è possibile scegliere una chiave di partizione per i dati transazionali con particolare attenzione all'inserimento dei dati e alle letture dei punti, mentre è possibile eseguire query tra partizioni con Collegamento ad Azure Synapse. Di seguito viene illustrato un esempio:
In un ipotetico scenario IoT globale, device id funge da chiave di partizione valida perché tutti i dispositivi generano un volume di dati simile, il che impedisce problemi di partizione ad accesso frequente. Tuttavia, se si vogliono analizzare i dati di più dispositivi, come "tutti i dati di ieri" o "totali per città", potrebbero verificarsi problemi poiché tali query sono query tra partizioni. Queste query possono compromettere le prestazioni transazionali perché usano parte della velocità effettiva nelle unità richiesta per l'esecuzione. Tuttavia, con Azure Synapse Link, è possibile eseguire queste query analitiche senza costi di unità di richiesta. Il formato a colonne dell'archivio analitico è ottimizzato per le query analitiche e Collegamento ad Azure Synapse supporta prestazioni ottimali con i runtime di Azure Synapse Analytics.
Tipi di dati e nomi di proprietà
L'articolo sulle regole di inferenza automatica dello schema elenca i tipi di dati supportati. Anche se i runtime di Azure Synapse possono elaborare tipi di dati supportati in modo diverso, i tipi di dati non supportati bloccano la rappresentazione nell'archivio analitico. Un esempio: quando si usano stringhe DateTime che seguono lo standard ISO 8601 UTC, i pool di Spark in Azure Synapse rappresentano queste colonne come string e i pool SQL serverless in Azure Synapse rappresentano queste colonne come varchar(8000).
Un altro problema è che Azure Synapse Spark non accetta tutti i caratteri. Mentre gli spazi vuoti sono accettati, i caratteri come i due punti, l'accento grave e la virgola non lo sono. Si supponga che l'elemento abbia una proprietà denominata "Nome, Cognome". Questa proprietà viene rappresentata nell'archivio analitico e il pool serverless di Synapse SQL può leggerla senza problemi. Tuttavia, poiché si trova nell'archivio analitico, Spark per Azure Synapse non può leggere i dati dell'archivio analitico, incluse tutte le altre proprietà. Al termine della giornata, non sarà possibile usare Spark per Azure Synapse se una proprietà usa i caratteri non supportati nel proprio nome.
Appiattimento dei dati
Ogni proprietà al livello superiore dei dati di Azure Cosmos DB diventa una colonna nell'archivio analitico. Le proprietà all'interno di oggetti o array annidati vengono archiviate come JSON nell'archivio analitico, mantenendone la struttura. Le strutture annidate richiedono un'elaborazione aggiuntiva da parte dei runtime di Azure Synapse per rendere flat i dati in formato strutturato, cosa che potrebbe risultare complessa negli scenari di Big Data.
L'elemento ha solo due colonne nell'archivio analitico, id e contactDetails. Tutti gli altri dati, email e phone, richiedono un'elaborazione aggiuntiva tramite funzioni SQL da leggere singolarmente.
{
"id": "1",
"contactDetails": [
{"email": "thomas@andersen.com"},
{"phone": "+1 555 555-5555"}
]
}
L'elemento ha tre colonne nell'archivio analitico, id, email e phone. Tutti i dati sono direttamente accessibili come colonne.
{
"id": "1",
"email": "thomas@andersen.com",
"phone": "+1 555 555-5555"
}
Suddivisione in livelli dei dati
Collegamento ad Azure Synapse consente di ridurre i costi per quanto riguarda gli aspetti seguenti:
- Numero inferiore di query in esecuzione nel database transazionale.
- Una PK ottimizzata per l'inserimento dei dati e le letture puntuali, riducendo l'ingombro dei dati, gli scenari di partizioni calde e le divisioni di partizioni.
- La suddivisione in livelli dei dati da analytical time-to-live (attl) è indipendente da transactional time-to-live (tttl). È possibile mantenere i dati transazionali nell'archivio transazionale per alcuni giorni, settimane, mesi e conservare i dati nell'archivio analitico per anni o per sempre. Il formato a colonne dell'archivio analitico comporta una compressione naturale dei dati, dal 50% al 90%. E il suo costo per GB è circa il 10% del prezzo attuale dell'archivio transazionale. Per altre informazioni sulle limitazioni correnti del backup, consultare la panoramica dell'archivio analitico.
- Nessun processo ETL in esecuzione nell'ambiente, ovvero non è necessario allocare unità richiesta per tali processi.
Ridondanza controllata
Questa tecnica è un'ottima alternativa per le situazioni in cui un modello di dati esiste già e non può essere modificato. Il modello di dati corrente non funziona correttamente con l'archivio analitico. Questo vantaggio esiste perché l'archivio analitico ha regole che limitano il numero di livelli per cui è possibile annidare i dati e il numero di proprietà che è possibile avere in ogni documento. Se i dati sono troppo complessi o hanno troppi campi, alcune informazioni importanti potrebbero non essere incluse nell'archivio analitico. In questo caso, è possibile usare il feed di modifiche di Azure Cosmos DB per replicare i dati in un altro contenitore, applicando le trasformazioni necessarie per un modello di dati descrittivo di Collegamento ad Azure Synapse. Di seguito viene illustrato un esempio:
Scenario
Il contenitore CustomersOrdersAndItems viene usato per archiviare gli ordini on-line, inclusi i dettagli dei clienti e degli articoli: indirizzo di fatturazione, indirizzo di consegna, metodo di consegna, stato di consegna, prezzo degli articoli e così via. Sono rappresentate solo le prime 1.000 proprietà e le informazioni chiave non sono incluse nell'archivio analitico, bloccando così l'utilizzo di Collegamento ad Azure Synapse. Il contenitore ha petabyte di record e non è possibile modificare l'applicazione e rimodellare i dati.
Un altro aspetto del problema è il volume di dati di grandi dimensioni. Miliardi di righe vengono usate costantemente dal reparto di analisi, cosa che impedisce di usare tttl per l'eliminazione di dati vecchi. La conservazione dell'intera cronologia dei dati nel database transazionale per esigenze analitiche impone di aumentare costantemente il provisioning delle unità richiesta, con un impatto sui costi. I carichi di lavoro transazionali e analitici competono contemporaneamente per le stesse risorse.
operazioni consentite
Soluzione con il feed di modifiche
- Il team di progettazione ha deciso di usare il feed di modifiche per popolare tre nuovi contenitori:
Customers,OrderseItems. Con il feed di modifiche, stanno normalizzando e appiattendo i dati. Le informazioni non necessarie vengono rimosse dal modello di dati e ogni contenitore ha quasi 100 proprietà, evitando la perdita di dati a causa dei limiti di inferenza automatica dello schema. - Questi nuovi contenitori hanno l'archivio analitico abilitato e il reparto di analisi usa Synapse Analytics per leggere i dati. In questo modo, si riduce l'utilizzo delle unità richiesta perché le query analitiche vengono eseguite in Synapse Apache Spark e nei pool SQL serverless.
- Il contenitore
CustomersOrdersAndItemsora ha un TTL (time-to-live) impostato per mantenere i dati solo per sei mesi, il che consente una riduzione dell'utilizzo di altre unità richiesta, perché è presente almeno un'unità richiesta per GB in Azure Cosmos DB. Meno dati, meno unità richiesta.
Risultati
Il vantaggio più importante che emerge da questo articolo è che la modellazione dei dati in uno scenario senza schema è importante come non mai.
Come non esiste un solo modo per rappresentare i dati in una schermata, così non esiste un solo modo per modellare i dati. È necessario comprendere l'applicazione e come produce, usa ed elabora i dati. Applicando le linee guida presentate qui, è possibile creare un modello che soddisfi le esigenze immediate dell'applicazione. Quando l'applicazione cambia, usare la flessibilità di un database senza schema per adattare ed evolvere facilmente il modello di dati.