MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Fattori operativi da considerare durante la modellazione dei dati di MongoDB

Nel mio blog precedente, Come utilizzare la modellazione dei dati MongoDB per migliorare le operazioni di throughput, abbiamo discusso i 2 principali approcci alla relazione di modellazione dei dati, ovvero l'incorporamento e il riferimento. La scalabilità di MongoDB dipende molto dalla sua architettura e, per essere precisi, dalla modellazione dei dati. Quando si progetta un DBM NoSQL, il punto principale da considerare è garantire documenti senza schema oltre a un numero ridotto di raccolte ai fini di una facile manutenzione. È incoraggiata una buona integrità dei dati, adottando la convalida dei dati attraverso alcune regole definite prima dell'archiviazione. L'architettura e il design di un database dovrebbero essere normalizzati e scomposti in più piccole raccolte per evitare la ripetizione dei dati, migliorare l'integrità dei dati e semplificare il recupero dei modelli. Con questo in atto, sei in grado di migliorare la coerenza dei dati, l'atomicità, la durabilità e l'integrità del tuo database.

La modellazione dei dati non è un'impresa secondaria in una fase di sviluppo dell'applicazione, ma una considerazione iniziale poiché molti aspetti dell'applicazione vengono effettivamente realizzati durante la fase di modellazione dei dati. In questo articolo discuteremo quali fattori devono essere considerati durante la modellazione dei dati e vedremo come influiscono sulle prestazioni di un database in generale.

Molte volte sarà necessario distribuire un cluster del database come un modo per aumentare la disponibilità dei dati. Con un modello di dati ben progettato puoi distribuire le attività a un cluster partizionato in modo più efficace, riducendo così le operazioni di throughput mirate a una singola istanza mongod. I principali fattori da considerare nella modellazione dei dati includono:

  1. Scalabilità
  2. Atomicità
  3. Prestazioni e utilizzo dei dati
  4. Sharding
  5. Indicizzazione
  6. Ottimizzazione dello spazio di archiviazione
  7. Struttura e crescita dei documenti
  8. Ciclo di vita dei dati

1. Scalabilità

Si tratta di un aumento del carico di lavoro di un'applicazione guidata dall'aumento del traffico. Molte applicazioni hanno sempre un'aspettativa nell'aumento del numero dei suoi utenti. Quando ci sono così tanti utenti serviti da una singola istanza di database, le prestazioni non soddisfano sempre le aspettative. In qualità di gestore di database, hai quindi il mandato di progettare questo DBM in modo tale che le raccolte e le entità di dati siano modellate in base alle esigenze presenti e future dell'applicazione. La struttura del database dovrebbe generalmente essere presentabile per facilitare il processo di replica e partizionamento orizzontale. Quando hai più shard, le operazioni di scrittura vengono distribuite tra questi shard in modo tale che per qualsiasi aggiornamento dei dati, viene eseguito all'interno dello shard contenente quei dati anziché cercare in un unico grande set di dati per eseguire un aggiornamento.

2. Atomicità

Questo si riferisce al successo o al fallimento di un'operazione come singola unità. Ad esempio, potresti avere un'operazione di lettura che implica un'operazione di ordinamento dopo aver recuperato il risultato. Se l'operazione di ordinamento non viene gestita correttamente, l'intera operazione non procederà quindi alla fase successiva.

Le transazioni atomiche sono serie di operazioni che non sono né divisibili né riducibili, quindi si verificano come entità singole o falliscono come operazioni singole. Le versioni di MongoDB precedenti alla 4.0 supportano le operazioni di scrittura come processi atomici a livello di singolo documento. Con la versione 4.0 è ora possibile implementare transazioni multi-documento. Un modello di dati che migliora le operazioni atomiche tende ad avere ottime prestazioni in termini di latenza. La latenza è semplicemente la durata entro la quale viene inviata una richiesta di operazione e quando viene restituita una risposta dal database. Per essere seccanti, è facile aggiornare i dati che sono incorporati in un unico documento piuttosto che in uno a cui si fa riferimento.

Consideriamo ad esempio il set di dati di seguito

{
    childId : "535523",
    studentName : "James Karanja",
    parentPhone : 704251068,
    age : 12,
    settings : {
        location : "Embassy",
        address : "420 01",
        bus : "KAZ 450G",
        distance : "4"
      }
}

Se vogliamo aggiornare l'età aumentandola di 1 e cambiando la località in Londra potremmo fare:

db.getCollection(‘students’).update({childId: 535523},{$set:{'settings.location':'London'}, $inc:{age:1}}).

Se ad esempio l'operazione $set fallisce, automaticamente l'operazione $inc non verrà implementata e in generale l'intera operazione fallisce.

Consideriamo invece i dati di riferimento tali che ci sono 2 raccolte una per lo studente e l'altra per le impostazioni.

Collezione studenti

{
    childId : "535523",
    studentName : "James Karanja",
    parentPhone : 704251068,
    age : 12
}

Raccolta delle impostazioni

{
  childId : "535523",  
  location : "Embassy",
  address : "420 01",
  bus : "KAZ 450G",
  distance : "4"
}

In questo caso puoi aggiornare i valori di età e posizione con operazioni di scrittura separate, ad esempio

db.getCollection(‘students’).update({childId: 535523},{$inc:{age:1}})
db.getCollection('settings’).update({childId: 535523 } , {$set: { 'settings.location':'London'}})

Se una delle operazioni fallisce, non influisce necessariamente sull'altra poiché vengono eseguite come entità diverse.

Transazioni per più documenti

Con MongoDB versione 4.0, ora puoi eseguire più transazioni di documenti per set di repliche. Ciò migliora le prestazioni poiché le operazioni vengono inviate a una serie di raccolte, database e documenti per un'elaborazione rapida. Quando una transazione è stata confermata i dati vengono salvati mentre se qualcosa va storto e una transazione fallisce, le modifiche apportate vengono annullate e la transazione viene generalmente interrotta. Non ci saranno aggiornamenti ai set di repliche durante la transazione poiché l'operazione è visibile solo all'esterno quando la transazione è stata completamente salvata.

Per quanto sia possibile aggiornare più documenti in più transazioni, viene fornito con una battuta d'arresto di prestazioni ridotte rispetto alle scritture di documenti singoli. Inoltre, questo approccio è supportato solo per il motore di archiviazione WiredTiger, quindi rappresenta uno svantaggio per i motori di archiviazione In-Memory e MMAPv1.

3. Prestazioni e utilizzo dei dati

Le applicazioni sono progettate in modo diverso per soddisfare scopi diversi. Ce ne sono alcuni che servono solo per i dati attuali come le applicazioni di notizie meteorologiche. A seconda della struttura di un'applicazione, si dovrebbe essere in grado di progettare un database ottimale corrispondente per server il caso d'uso richiesto. Ad esempio, se si sviluppa un'applicazione che recupera i dati più recenti dal database, l'utilizzo di una raccolta limitata sarà l'opzione migliore. Una raccolta limitata migliora il funzionamento ad alto rendimento proprio come un buffer in modo tale che quando lo spazio allocato viene sfruttato, i documenti più vecchi vengono sovrascritti e i documenti possono essere recuperati nell'ordine in cui sono stati inseriti. Considerando il recupero dell'ordine di inserimento, non sarà necessario utilizzare l'indicizzazione e l'assenza di un sovraccarico dell'indice migliorerà ugualmente il throughput di scrittura. Con una raccolta limitata, i dati associati sono piuttosto piccoli in quanto possono essere mantenuti all'interno della RAM per un po' di tempo. I dati temporali in questo caso sono archiviati nella cache che è abbastanza letta rispetto alla scrittura, rendendo così l'operazione di lettura abbastanza veloce. Tuttavia, la raccolta limitata presenta alcuni svantaggi come, ad esempio, non è possibile eliminare un documento a meno che non si elimini l'intera raccolta, qualsiasi modifica alle dimensioni di un documento fallirà l'operazione e, infine, non è possibile dividere una raccolta limitata.

Diverse sfaccettature sono integrate nella modellazione dei dati di un database a seconda delle esigenze di utilizzo. Come si è visto, le applicazioni di report tenderanno a richiedere una lettura più intensiva, quindi il design dovrebbe essere in modo da migliorare il throughput di lettura.

4. Frazionamento

Le prestazioni tramite il ridimensionamento orizzontale possono essere migliorate mediante il partizionamento orizzontale poiché i carichi di lavoro di lettura e scrittura sono distribuiti tra i membri del cluster. La distribuzione di un cluster di shard tende a partizionare il database in più raccolte di piccole dimensioni con documenti distribuiti a seconda di una chiave shard. È necessario selezionare una chiave shard appropriata che possa impedire l'isolamento della query oltre ad aumentare la capacità di scrittura. Una migliore selezione riguarda generalmente un campo presente in tutti i documenti all'interno della raccolta mirata. Con lo sharding, aumenta lo spazio di archiviazione poiché man mano che i dati crescono, vengono stabiliti più shard per contenere un sottoinsieme di questo cluster.

5. Indicizzazione

L'indicizzazione è uno dei migliori approcci per migliorare il carico di lavoro di scrittura, soprattutto dove i campi si trovano in tutti i documenti. Quando si esegue l'indicizzazione, si dovrebbe considerare che ogni indice richiederà 8 KB di spazio dati. Inoltre, quando l'indice è attivo, consumerà spazio su disco e memoria, quindi dovrebbe essere monitorato per la pianificazione della capacità.

Multiplenines Diventa un DBA MongoDB - Portare MongoDB in produzioneScopri cosa devi sapere per distribuire, monitorare, gestire e ridimensionare MongoDBScarica gratuitamente

6. Ottimizzazione dell'archiviazione

Molti piccoli documenti all'interno di una raccolta tenderanno a occupare più spazio rispetto a quando hai pochi documenti con documenti incorporati. Durante la modellazione, è quindi necessario raggruppare i dati correlati prima dell'archiviazione. Con pochi documenti, un'operazione di database può essere eseguita con poche query, quindi un accesso casuale al disco ridotto e ci saranno meno voci chiave associate nell'indice corrispondente. Le considerazioni in questo caso quindi saranno:utilizzare l'incorporamento per avere meno documenti che a loro volta riducono l'overhead per documento. Utilizzare nomi di campo più brevi se in una raccolta sono coinvolti meno campi in modo da non rendere significativo il sovraccarico del documento. I nomi dei campi più brevi riducono l'espressività, ad esempio

{ Lname : "Briston", score : 5.9 }

salverà 9 byte per documento invece di utilizzare

{ last_name : "Briston", high_score: 5.9 }

Usa il campo _id in modo esplicito. Per impostazione predefinita, i client MongoDB aggiungono un campo _id a ciascun documento assegnando un ObjectId a 12 byte univoco per questo campo. Inoltre, il campo _id verrà indicizzato. Se i documenti sono piuttosto piccoli, questo scenario rappresenterà una quantità significativa di spazio nel numero complessivo di documenti. Per l'ottimizzazione dell'archiviazione, è possibile specificare il valore per il campo _id in modo esplicito quando si inseriscono documenti in una raccolta. Tuttavia, assicurati che il valore sia identificato in modo univoco perché funge da chiave primaria per i documenti nella raccolta.

7. Struttura e crescita del documento

Ciò si verifica in seguito all'operazione di push in cui i documenti secondari vengono inseriti in un campo di matrice o quando vengono aggiunti nuovi campi a un documento esistente. La crescita del documento presenta alcune battute d'arresto, ad esempio per una raccolta limitata, se la dimensione viene modificata, l'operazione fallirà automaticamente. Per un motore di archiviazione MMAPv1, le versioni precedenti alla 3.0 riposizionano il documento su disco se la dimensione del documento viene superata. Tuttavia, nelle versioni successive a partire dalla 3.0, esiste un concetto di Power of 2 Sized Allocations che riduce le possibilità di tali riallocazioni e consente il riutilizzo efficace dello spazio di registrazione liberato. Se prevedi che i tuoi dati crescano, potresti voler riorganizzare il tuo modello di dati per utilizzare i riferimenti tra i dati in documenti distinti anziché utilizzare un modello di dati denormalizzato. Per evitare la crescita dei documenti, puoi anche considerare l'utilizzo di una strategia di pre-allocazione.

8. Ciclo di vita dei dati

Per un'applicazione che utilizza solo i documenti inseriti di recente, considera l'utilizzo di una raccolta limitata le cui caratteristiche sono state discusse in precedenza.

Puoi anche impostare la funzione Time to Live per la tua collezione. Questo è abbastanza applicabile per i token di accesso nella funzione di reimpostazione della password per un'applicazione.

Time To Live (TTL)

Questa è un'impostazione di raccolta che consente a mongod di rimuovere automaticamente i dati dopo una durata specificata. Per impostazione predefinita, questo concetto viene applicato ai dati degli eventi generati dalla macchina, ai registri e alle informazioni sulle sessioni che devono persistere per un periodo di tempo limitato.

Esempio:

db.log_events.createIndex( { "createdAt": 1 }, { expireAfterSeconds: 3600 } )

Abbiamo creato un indice createAt e specificato un valore di requireAfterSeconds di 3600 che è 1 ora dopo il momento della creazione. Ora se inseriamo un documento come:

db.log_events.insert( {
   "createdAt": new Date(),
   "logEvent": 2,
   "logMessage": "This message was recorded."
} )

Questo documento verrà cancellato dopo 1 ora dal momento dell'inserimento.

È inoltre possibile impostare un'ora specifica dell'orologio in cui si desidera eliminare il documento. Per farlo, crea prima un indice, ad esempio:

db.log_events.createIndex( { "expireAt": 1 }, { expireAfterSeconds: 0 } )

Ora possiamo inserire un documento e specificare l'ora in cui deve essere cancellato.

db.log_events.insert( {
   "expireAt": new Date(December 12, 2018 18:00:00'),
   "logEvent": 2,
   "logMessage": "Success!"
} )

Questo documento verrà eliminato automaticamente quando il valore di expireAt è più vecchio del numero di secondi specificato in requireAfterSeconds, ovvero 0 in questo caso.

Conclusione

La modellazione dei dati è un'impresa ampia per qualsiasi progetto di applicazione al fine di migliorare le prestazioni del database. Prima di inserire i dati nel tuo db, considera le esigenze dell'applicazione e quali sono i migliori modelli di modelli di dati che dovresti implementare. Inoltre, aspetti importanti delle applicazioni non possono essere realizzati fino all'implementazione di un modello di dati adeguato.