2012-08-01 9 views
9

Ho cercato di ottenere una buona conoscenza dello storage di Azure Table per un po 'di tempo e, mentre capisco in generale come funziona, sto davvero cercando di scuotere il pensiero del mio database relazionale. Di solito imparo meglio con l'esempio, quindi mi chiedo se qualcuno può darmi una mano. Descriverò una semplice configurazione per come risolverei un problema utilizzando un database relazionale, qualcuno può aiutarmi a convertirli per utilizzare l'archiviazione di Azure Table?Come è possibile scuotere il pensiero del database relazionale per progettare un archivio dati di archiviazione tabella azzerato?

Diciamo che ho un'app per appunti semplice, ha utenti e ogni utente può avere tutte le note che desidera e ogni nota può avere quanti utenti (proprietari o spettatori) di cui ha bisogno. Se dovessi schierare questa operazione utilizzando un database relazionale avrei probabilmente schierarlo come segue:

Per il database, mi piacerebbe iniziare con qualcosa di simile:

CREATE TABLE [dbo].[Users](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [Username] [nvarchar](20) NOT NULL) 

CREATE TABLE [dbo].[UsersNotes](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [UserID] [int] NOT NULL, 
    [NoteID] [int] NOT NULL) 

CREATE TABLE [dbo].[Notes](
    [ID] [int] IDENTITY(1,1) NOT NULL, 
    [NoteData] [nvarchar](max) NULL)   

Vorrei quindi impostare una relazione tra Users.ID and UsersNotes.UserID e Notes.ID and UsersNotes.NoteID con vincoli per imporre l'integrità referenziale.

Per l'applicazione, avrei un ORM generare alcune entità con corrispondenti proprietà del nome per ognuno di questi, e probabilmente sarei chiamare un giorno:

public class Users 
{ 
    public int ID { get; set; } 
    public String Username { get; set; } 
} 
// and so on and so forth 

mi rendo conto che questo disegno è completamente dipendente sul database relazionale, e quello che sto cercando è qualche consiglio su come scuotere questo ragionamento per usare lo storage di Azure Table, o qualsiasi altra tecnica di memorizzazione dei dati non relazionali.

Supponiamo inoltre di aver installato l'SDK di Azure e di averlo giocato, ma le mie conoscenze sull'utilizzo dell'SDK sono limitate, preferisco non concentrarmi su questo, ma piuttosto su quale sarebbe una buona soluzione per quanto sopra. Un buon punto di partenza aiuterà a rendere sensato l'SDK, poiché avrò un punto di riferimento.

Per ragioni di completezza, consente di dire che

  • tecniche Nota cambieranno frequentemente quando creato per primo, e il ridursi nel tempo
  • Gli utenti avranno molte note, e le note possono avere più utenti (non concorrenti, solo gli spettatori)
  • mi aspetto abbastanza pochi utenti (poche centinaia), ma mi aspetto un buon numero di note (poche centinaia, per utente)
  • mi aspetto di interrogare contro Username di più, e poi mostrare le note l'utente ha accesso a
  • Mi aspetto anche durante la visualizzazione di una nota, per mostrare gli altri utenti con accesso a tale nota, una ricerca inversa
+0

La domanda è "come" ma la mia domanda è "perché"? Lo hai valutato in SQL Azure? 1 TB di file di registro è ATS. 10 GB di relazionale è SQL. In mezzo a un'ulteriore analisi. Ma 10 GB di relazione sono molti dati. – Paparazzi

+2

@Blam Sono interessato a un esercizio di apprendimento e al costo. – Nate

+0

Cool ma SO è per domande di programmazione specifiche. Se vuoi imparare ci sono molti libri e materiale online. – Paparazzi

risposta

5

Alcuni pensieri ...

  1. Pensate entità distinte nella loro interezza, e astenersi da decomposizione ulteriormente utilizzando qualsiasi tecnica di normalizzazione.
  2. Inventare un singolo identificativo per ciascuna entità, che se indicizzato, consentirebbe sia una ricerca esatta della chiave, sia una ricerca di chiave di intervallo per corrispondere.
  3. Dividere l'identificatore in 2 segmenti per esigenze di scalabilità di archiviazione della tabella Azure. Come dividere bene, è un argomento separato da solo, ma in genere la suddivisione in segmenti naturali ben definiti funziona abbastanza bene.

Nel tuo esempio, le due entità sarebbero Utente e Nota.

Un ID utente sarebbe sufficiente per identificare un utente in modo univoco. Una ricerca di intervalli su un utente potrebbe non essere davvero utile. L'id utente potrebbe essere qualsiasi valore di lunghezza fissa qui.

Un ID utente + NoteId sarebbe sufficiente per identificare in modo univoco una nota. L'id della nota potrebbe essere qualcosa come una data/timestamp + un GUID per l'unicità. Tale chiave, in combinazione con l'ID utente, identificherà in modo univoco la nota e consentirà la ricerca di intervalli su tutte le note dell'utente o le note dell'utente in un determinato periodo di tempo.

Quindi se UserId = "ABCD", NoteId potrebbe essere "20120801- 00f64829-6044-4fbb-8b4e-ae82ae15096e".

È possibile memorizzare entrambe le entità nello stesso o in tabelle diverse. Ecco alcuni approcci differenti ...

Se ogni entità ha la propria tabella,

  • Per una chiave di partizione utente potrebbe essere “ABCD” e Key Row potrebbe essere in realtà nulla e di cercare solo sulla partizione chiave.

  • Oppure la chiave di partizione potrebbe essere "AB" e la chiave di riga potrebbe essere "CD".

    Entrambe le suddette potrebbero scalare bene per un numero elevato di utenti.

  • Oppure la chiave di partizione potrebbe essere "*" e la chiave di riga potrebbe essere "ABCD". Questo potrebbe funzionare abbastanza bene per un gruppo più piccolo di utenti e potresti inserire sia gli utenti che le note nella stessa tabella.

per una nota

  • partizione chiave potrebbe essere “ABCD” e Key Row potrebbe essere “20120801- 00f64829-6044-4fbb-8b4e-ae82ae15096e”

  • ricerca Gamma qui potrebbe essere

    • Su PartitionKey = "ABCD" per ottenere tutte le note per un utente.
    • On PartitionKey = "ABCD" e RowKey> = "20120801" e RowKey < = "20120901" per ottenere le note all'interno di un intervallo di date.

UPDATE

ho letto male la tua domanda e assunto solo uno a molti tra gli utenti e le note. Dal momento che c'è una relazione molti a molti, occorrerebbero 4 entità da modellare, a meno che non ti interessi la duplicazione. (Se le note sono brevi e immutabili, possono essere duplicate e non è necessario modellare i join).

Più di 1 entità può essere inserita in una singola tabella se i tasti si trovano in intervalli di chiavi diversi e possono essere facilmente distinti. Anche se, in pratica, questo non è comune a meno che non vi sia un bisogno specifico, in genere le scritture transazionali nella stessa partizione (non applicabile lì).

Quindi uno schema di tabella singolo potrebbe assomigliare a questo. Per più tabelle, il prefisso Key Partition potrebbe essere eliminato.

  • Si può anche modellare questo in 3 tabelle, una per Utente, una per Note e una per le relazioni in entrambe le direzioni.
  • È anche possibile modellarlo parzialmente in SQL e parzialmente in Archiviazione di Azure. Note e dati utente in blob o tabelle e relazioni in SQL.

.

Entity  Partition Key    Row Key    
User   “U” + UserId  
Note   “N” + NoteId(Date)   NodeId(GUID) 
User Note  “X“ + UserId    NoteId(Date+GUID) 
Note User  “Y“ + NoteId(Date+GUID) UserId  

Queste sono alcune alternative e vorrete determinare quale si adatta meglio ai vostri dati e alle vostre esigenze.

ANCORA un altro aggiornamento
realtà 3 soggetti dovrebbe essere sufficiente con la nota nell'entità UserNote.

Se UserId = GUID
E NoteID = Data + GUID

Entity  Partition Key Row Key    Note User   
User  UserId  
User Note UserId   NoteId(Date+GUID) Note   (Contains Note and can query for all notes for a user). 
Note User NoteId(Date) NodeId(GUID)    UserId (Can query for all Users of a note. Join on ‘User Note’ to get note.) 
+0

Puoi approfondire un po 'su come memorizzare entrambe le entità in un unico tavolo? Inoltre hai saltato la mia tabella UsersNotes perché non è necessaria? – Nate

+0

@Nate. Ho letto male le domande. Si prega di vedere la mia risposta aggiornata. – hocho

+0

Apprezzo molto il tuo aiuto. Innanzitutto, i miei appunti non sono immutabili, probabilmente gli utenti li cambieranno abbastanza frequentemente. In secondo luogo, è saggio memorizzarli in una tabella? Se li memorizzo in tre tabelle e continuo a modellare il concetto relazionale, e manualmente impone l'integrità referenziale nella mia app, sto sconfiggendo lo scopo di utilizzare lo storage della tabella in primo luogo? Inoltre, da dove proviene NoteId (Date)?) – Nate

5

Si può pensare a tabelle Azure come raccolte di oggetti.

Nel linguaggio della Tabella Azzurra, un oggetto è un'entità.

Per utilizzare l'esempio, gli utenti derivano da TableStorageEntity.

L'archiviazione tabella di Azure non è relazionale. Non ci sono join. Ma c'è LINQ, un linguaggio di query supportato in varie lingue. Quindi unire le operazioni e l'integrità referenziale non è fornita dal sistema. Lo sviluppatore deve farlo.

alcuni vantaggi significativi:

(1) tavoli Azure scala automaticamente su più nodi di storage per mantenere le prestazioni, anche se si tratta di miliardi di entità. (2) Vengono replicati 3 volte (3) Vengono forniti con uno SLA (4) L'API del servizio di tabella è compatibile con l'API REST, quindi è possibile accedervi da tecnologie non Microsoft.

Per consentire agli oggetti di essere archiviati nelle tabelle di Azure, è sufficiente derivare da TableStorageEntity.

Ulteriori informazioni sono disponibili se si esegue la ricerca di "Laboratori virtuali di tabelle Microsoft Azure".

Lo snippet in basso ignora (1) tasto di sequenza chiave (2). Ma questo è qualcosa di cui devi preoccuparti. Pensa che le due chiavi siano la chiave primaria su una tabella relazionale.

È necessario pensare a queste due chiavi con molta attenzione. Determinano la prestazione. Poiché si ottiene un solo set di chiavi, potrebbe essere necessario mantenere copie de-normalizzate dei dati per ottenere prestazioni ottimali.

 
    public class Users : TableStorageEntity 
    { 
     public int ID { get; set; } 
     public String Username { get; set; } 
    } 

Controllare le mani. I tavoli Azure sono economici e facili da usare.

+0

... "non" è necessario preoccuparsi? –

+0

Quindi, dovrei creare solo tre tabelle azzurre separate e unire manualmente i dati tramite LINQ? In sostanza basta mantenere la configurazione relazionale, solo manualmente applicarla? – Nate

1

Perché UsersNotes hanno un ID? Perché non solo UserID, NoteID come chiave primaria composta?

Quindi tre tabelle con 2 proprietà ciascuna. Il primo è PartitionKey e il secondo è RowKey.

Se ci si aspetta di interrogare su NoteID per ottenere ID utente molto, una quarta tabella come ricerca su PartitionKey è più veloce della ricerca su RowKey. E di solito sarà più economico in quanto comporta meno transazioni. Ma hai le transazioni per caricare la tabella.

public class NotesUsers : TableStorageEntity 
    { 
     public int NoteID { get; set; } 
     public int UserID { get; set; } 
    } 

E per la tabella Utenti utilizzare UserName come PartitionKey se si tratta della condizione di query comune.

Non esiste alcuna integrità referenziale dichiarativa in ATS. Dovrai applicare tutte le relazioni dati nella tua applicazione. Chiave composita in due parti. Una ricerca su RowKey è come una scansione (non una ricerca). Dove una ricerca su PartitionKey è come una ricerca.

Ma vorrei andare SQL. Se le note sono digitate da qualcuno, allora si tratta di un volume relativamente basso di dati. Ed è dati relazionali.

+0

UsersNotes ha un ID fuori protocollo/abitudine. Suppongo che non sia esplicitamente necessario.Capisco che l'integrità referenziale deve essere implementata nel codice della mia app. Forse la mia domanda dovrebbe essere: "Perdo i benefici dell'utilizzo dello storage da tavolo, modellando i miei dati relazionali e implementando manualmente l'integrità referenziale?" - Avevo l'impressione che per utilizzare efficacemente ATS, dovevi modellare i tuoi dati in modo diverso (non relazionale) ma forse mi sbaglio? – Nate

+0

Se l'ID non è necessario, perché utilizzarlo, UsersNotes. Torna al mio commento originale di SO è per domande di programmazione specifiche. Hai letto la mia risposta? La tabella di aggiunta NotesUsers è un esempio di come il modello di tabella sarebbe diverso in ATS da SQL. In SQL non vorrei mettere il nome utente prima. – Paparazzi

Problemi correlati