Table of Contents
A differenza dei database relazionali tradizionali, i sistemi NoSQL hanno spesso architetture e meccanismi di querying diversi, che influenzano la gestione della selezione. Un'operazione di smistamento poco pianificata può causare elevata latenza, aumento del consumo di memoria e throughput degradato. Per costruire applicazioni veloci e scalabili, gli sviluppatori devono comprendere il motore di storage sottostante, le capacità di indicizzazione e la selezione dei dati primitivi.
Questo articolo esplora i concetti fondamentali che stanno dietro la selezione nei database NoSQL, delinea strategie pratiche per una selezione efficiente e fornisce indicazioni attuabili per ottimizzare le prestazioni in scenari reali.
Comprendere i modelli di dati NoSQL e le implicazioni di selezione
I database NoSQL sono disponibili in diversi tipi: documento, valore chiave, colonna-famiglia e grafico. Ogni modello memorizza i dati in modo diverso, e queste differenze influiscono notevolmente su come la selezione può essere implementata in modo efficiente.
Database di documenti
I database dei documenti come MongoDB e Couchbase memorizzano i dati come documenti JSON, tipicamente nelle collezioni. Sostiene le domande ricche con la selezione, il filtraggio e l'aggregazione. La selezione nei database dei documenti viene spesso eseguita sui campi all'interno dei documenti. Poiché i documenti possono avere strutture nidificati, la selezione su sottocampi (ad esempio, order.items.price
Negozi di valori chiave
I negozi di valori chiave come Redis, Amazon DynamoDB (in modalità key-value), e Riak sono ottimizzati per semplici lookups con la chiave primaria. La selezione tra i valori non è nativo; invece, gli utenti spesso si affidano alle strutture di dati ordinate (ad esempio, Redis set ordinati) o alla selezione a livello di applicazione.
Database di Familia Colonna
I database delle colonne sono raggruppati in famiglie di colonne, come Apache Cassandra e HBase. La selezione è strettamente accoppiata con la chiave di riga e le colonne di clustering. Cassandra, ad esempio, memorizza i dati sul disco nell'ordine definito dal RIMARY KEY]] (le colonne di partizione + colonne di cluster)
Database del grafico
La selezione avviene in genere su proprietà nodi o proprietà di relazione. Le query traversali del grafico spesso recuperano piccoli sottografi localizzati, quindi la selezione della testa è di solito minima. Tuttavia, quando si selezionano tra molti nodi (ad esempio, trovando i 100 nodi più collegati), l'indicizzazione sulle proprietà è cruciale.
Strategie per una selezione efficiente
La selezione efficiente in NoSQL dipende dall’allineamento del vostro approccio con i punti di forza del database.Le seguenti strategie si applicano in diversi tipi di NoSQL, con dettagli specifici di implementazione per ogni sistema.
Indice delle levaggi
Quando una query include una clausola ]sort[[]]], il database può leggere i dati direttamente in ordine indice ordinato, evitando una scansione completa e in-memoria sorta. La maggior parte dei database NoSQL supporta gli indici secondari, anche se il loro comportamento varia.
- MongoDB:] Creare indici composti che corrispondono sia al filtro che ai campi di sorta. Ad esempio db.collection.createIndex({ stato: 1, creatoAt: -1 })]] supporta la selezione di status e
- Cassandra:[] La selezione è implicita tramite colonne di raggruppamento. Se è necessario ordinare da una colonna diversa, è necessario modellare i dati in modo diverso (ad esempio, creare una tabella separata con l'ordine di clustering desiderato) o denormalizzare.
- DynamoDB:[] Usare un indice secondario locale (LSI) o un indice secondario globale (GSI) con una chiave di selezione. Le query possono quindi specificare ScanIndexForward] per controllare l'ordine discendente/ascending.
Gli indici sono a un costo: richiedono lo storage e possono rallentare gli scritti. Scegliere gli indici saggiamente, priorità le domande più comuni di tipo.
Utilizzare le funzionalità di selezione integrate
La maggior parte delle lingue di query NoSQL supporta una clausola sort[]]] o []order by[]]. Utilizzando queste è quasi sempre più veloce che ordinare in codice di applicazione perché il database può sfruttare gli indici e eseguire l'operazione vicino ai dati.
Esempi includono il metodo di MongoDB sort()], il metodo di Couchbase [ORDER BY[] in N1QL, e l'ordine implicito di Cassandra tramite colonne di raggruppamento. Anche quando una query non utilizza un indice, le routine di ordine interno del database sono solitamente più efficienti di una nave.
Ordinare al livello di applicazione quando appropriato
La selezione a livello di applicazione dovrebbe essere un fallback, non un default. Tuttavia, ci sono scenari in cui ha senso:
- Il set di dati è già piccolo (ad esempio, i risultati impaginati da una query filtrata).
- La logica di selezione è troppo complessa per il database (ad esempio, algoritmi di ranking personalizzati).
- Il database non dispone di supporto di selezione nativo (ad esempio, molti negozi di valore chiave).
Quando si seleziona nell'applicazione, recuperare solo i dati necessari (usare [limit[] e la proiezione) e ordinare in memoria.
Ottimizzare lo schema dei dati per la selezione
Il design dello schema ha un profondo impatto sulle prestazioni di selezione.
- Pre-sorzionando:[] Scrivi i dati nell'ordine desiderato. Ad esempio, in Cassandra, scegli colonne di raggruppamento che corrispondono alle esigenze di ordine comune. In MongoDB, puoi usare collezioni incise o memorizzare timestamp che normalmente ordinano l'inserimento.
- Denormalizzazione:[] Duplicare i dati in modo che sia memorizzato nell'ordine necessario per una specifica query.
- Utilizza di array o documenti incorporati:[ Nei database dei documenti, memorizzare i sub-array ordinati (ad esempio, ID dei commenti ordinati) per evitare la selezione in tempo di lettura.
L'ottimizzazione dello schema deve sempre considerare i modelli di scrittura e la coerenza dei dati.
Ordinazione di grandi dataset: Tecniche avanzate
Quando i dataset crescono oltre la capacità di un singolo nodo o superano i limiti di memoria, la selezione richiede strategie distribuite.
Limiti di Risultato Set e utilizzo Paginazione
La maggior parte dei database NoSQL supportano i parametri LIMIT[] o ]pageSize]. Combinato con gli indici, questo consente al database di ordinare solo i migliori risultati N, evitando una sorta di tutti i documenti corrispondenti. Pagina- con l'impostazione di tasti (ricorso-percorso-basso) pagina di pagina è più efficiente
Sharding levante per la selezione parallela
Ogni shard può ordinare in modo indipendente la sua parte dei dati e un coordinatore fonde i risultati ordinati. Questa è la base della strategia sort-merge utilizzata in sistemi come MongoDB (con cluster sharded) e Apache Cassandra (utilizzando il nodo coordinatore).
- In MongoDB,] il sort()[] operazione su una collezione sharded richiede che il campo di selezione sia incluso nella chiave shard o che la query sia indirizzata a un singolo shard Altrimenti, il router (mongotensi) deve raccogliere tutti i documenti corrispondenti da ogni shard e ordinarli in memoria, che possono essere lento.
- In Cassandra,[]] la selezione tra le partizioni non è supportata in una sola query. È necessario recuperare i dati da ogni partizione e fondersi a livello di applicazione, o ridisegnare lo schema per evitare la selezione delle parti incrociate.
Quando si utilizza sharding, progettare la chiave shard per ridurre al minimo le operazioni di scatter-gather per domande di genere comuni.
Pianta di vuotoRidurre o Aggregazione Pipeline
I requisiti complessi di selezione possono essere gestiti da pipeline MapReduce o aggregation, che distribuiscono il lavoro in tutto il cluster.
- Il gasdotto di aggregazione di MongoDB[[]] include una fase [], che può essere posizionata presto nel condotto per ridurre il volume dei documenti passati alle fasi successive. Se un ] fase segue una $match[F
- Apache Hadoop MapReduce[[]] ordina i dati implicitamente durante la fase dello shuffle – i tasti vengono ordinati prima di essere passati ai riduttori.
- Apache Spark[] può leggere da fonti NoSQL (ad esempio Cassandra tramite il connettore Spark) e ordinare enormi set di dati attraverso i nodi utilizzando la propria gestione della memoria e partizionamento.
Per le domande operative (tempo di risposta di secondo), le pipeline di aggregazione sono preferite su MapReduce, che è tipicamente più lento e più pesante.
Migliori Pratiche per Sistemi NoSQL Diverse
L'implementazione di una selezione efficiente richiede conoscenze specifiche del database. Di seguito sono raccomandazioni concrete per i motori NoSQL più popolari.
Mongol.
- Indicizzare sempre i campi che si selezionano. Utilizzare indici composti che coprono i filtri di query e ordinare ordina.
- Evitare di ordinare su campi con elevata cardinalità che non fanno parte di un indice composto – il database può rientrare in una sorta di memoria in-memoria, che è bloccato dal sort] limite di memoria (32 MB per impostazione predefinita).
- Utilizzare la pipeline di aggregazione $sort[] dopo i primi []$match] stadi per minimizzare i dati che scorre attraverso.
- Per i dati della serie temporale, utilizzare il createIndex({ timestamp: -1 })[]] pattern – gli indici discendenti sono ideali per le domande più recenti.
Cassandra
- Modelli le tabelle in modo che le colonne di clustering corrispondano all'ordine di selezione di cui hai bisogno. Puoi avere più tabelle con diversi ordini di clustering per gli stessi dati (denormalizzazione).
- Non fare affidamento su ORDER BY[] – consente solo di riordinare all'interno della direzione di clustering esistente. Non è possibile aggiungere nuove colonne per la selezione al momento della domanda.
- Usare le viste materializzate con parsimonia: creano tavoli aggiuntivi che vengono mantenuti automaticamente, ma aggiungono la sovraccarica di scrittura e hanno limitazioni note.
- Tenere le partizioni piccole (fewer di 100.000 righe per partizione) per evitare di ordinare latenza all'interno di una partizione.
Dinamo
- Utilizzare una chiave primaria composita con una chiave di selezione (chiave di linea) per attributo che è necessario ordinare su.
- Per ordinare su attributi non-chiave, creare un GSI con quell'attributo come la chiave di selezione.
- Usa ScanIndexForward[]] impostato su [false[] per ordine discendente – è efficiente e utilizza l'indice.
- Evitare di ordinare su grandi set di risultati; DynamoDB limita i risultati delle domande a 1 MB per richiesta.
Redi
- Set ordinati (ZADD[]], [ZRANGE[]]) sono il meccanismo primario per la selezione. Mantengono un ordine ordinato per punteggio, ideale per classifiche, serie temporali o qualsiasi ordine numerico.
- Per i valori delle stringhe, utilizzare il comando SORT[], ma blocca il server e non deve essere utilizzato su grandi liste.
- Se avete bisogno di ordinare oggetti complessi, memorizzarli come hashes con un set ordinato di ID, quindi recuperare oggetti per ID nell'ordine ordinato.
Couchbase
- N1QL supporta ORDER BY[]. Utilizzare gli indici di copertura (indice che includono tutti i campi della query) per evitare l'ottenimento di documenti.
- Per l'analisi ad-hoc, utilizzare il Servizio Analytics (un superset di N1QL) che può sfruttare l'architettura MPP per la selezione di grandi set di dati.
Prestazioni Pitfalls da evitare
Anche gli sviluppatori esperti possono cadere in trappole che degradano le prestazioni di selezione.
- Sorting senza un indice su una grande collezione. Questo forza una sorta di memoria in-memoria, che può fallire (MongoDB lancia un errore) o causare alta latenza e la pressione della memoria.
- Utilizzando ]ORDER BY[] con una colonna casuale in Cassandra.[ Cassandra supporta solo l'ordine raggruppando colonne nell'ordine dichiarato.
- Fetching tutti i documenti corrispondenti per ordinare a livello di applicazione. Filtra sempre aggressivo e utilizzare la paginazione per portare il risultato impostato a una dimensione gestibile.
- L'ordine di un campo con bassa selettività] Un indice su un campo di bassa cartilina (ad esempio un booleano) offre poco vantaggio di selezione perché molti documenti condividono lo stesso valore, causando una specie secondaria o I/O casuale.
- Ignorando i limiti di memoria.[ I database hanno spesso dei limiti duri sulla quantità di memoria consentita per la selezione.
Conclusioni
La selezione dei dati efficiente nei database di NoSQL dipende dalla comprensione del modello di dati specifico e dall'utilizzo di adeguate tecniche di indicizzazione, progettazione e elaborazione degli schemi. Non esiste una soluzione one-size-fits‐all: una strategia di selezione che funziona perfettamente in MongoDB può essere impossibile in Cassandra, e ciò che è banale in Redis potrebbe essere estremamente costoso in DynamoDB.
Inizia analizzando i tuoi modelli di accesso: quali campi saranno ordinati più spesso, e quali sono le dimensioni previste del set di risultati? Da lì, progetta il tuo schema e gli indici per supportare quei modelli in modo nativo. Quando le query superano le capacità di un singolo nodo, consideri sharding, aggregazione pipelines, o offloading smistamento di un motore di analisi dedicato.
Per ulteriori informazioni, consultare la ]MongoDB documentazione di ordine[, []Cassandra che ordina la colonna di raggruppamento, e la DynamoDB sort key design guide].