Ho una domanda relativa alla progettazione dello schema HBase. Il problema è abbastanza semplice: sto memorizzando "notifiche" in hbase, ognuna delle quali ha uno stato ("nuovo", "visto" e "letto"). Qui ci sono le API ho bisogno di fornire:Progettazione dello schema HBase per supportare al meglio query specifiche
- Ottenere tutte le notifiche di un utente
- Ricevi tutte le "nuove" le notifiche per un utente
- ottenere il conteggio di tutti i "nuovi" notifiche per un utente
- Aggiorna stato per una notifica
- Aggiorna stato per tutte le notifiche di un utente
- ottenere tutti i "nuovi" notifiche attraversato la banca dati
- notifiche sho potrebbe essere scansionabile in ordine cronologico inverso e consentire l'impaginazione.
Ho un paio di idee, e volevo vedere se uno di loro è chiaramente migliore, o se ho perso una buona strategia del tutto. Comune a tutti e tre, penso che avere una riga per ogni notifica e avere l'id utente nella riga di comando sia la strada da percorrere. Per ottenere un ordinamento cronologico per l'impaginazione, devo anche avere un timestamp inverso. Mi piacerebbe mantenere tutte le note in una tabella (quindi non devo unire l'ordinamento per la chiamata "get all notificatiosn per un utente") e non voglio scrivere processi batch per le tabelle indice secondarie (poiché gli aggiornamenti a il conteggio e lo stato dovrebbero essere in tempo reale).
Il modo più semplice per farlo sarebbe (1) la chiave di riga è "userId_reverseTimestamp" e filtrare lo stato sul lato client. Ciò sembra ingenuo, poiché invieremo molti dati non necessari attraverso la rete.
La prossima possibilità è di (2) codificare lo stato anche nel tasto di riga, quindi "userId_reverseTimestamp_status" e quindi eseguire il filtro regex di rowkey sulle scansioni. Il primo problema che vedo è la necessità di cancellare una riga e copiare i dati di notifica in una nuova riga quando lo stato cambia (che presumibilmente dovrebbe accadere esattamente due volte per ogni notifica). Inoltre, poiché lo stato è l'ultima parte della riga di comando, per ciascun utente, analizzeremo molte altre righe. È un grande successo per le prestazioni? Infine, per cambiare lo stato, dovrò sapere qual è stato lo stato precedente (per costruire la chiave di riga) altrimenti avrò bisogno di fare un'altra scansione.
L'ultima idea che ho avuto è (3) avere due famiglie di colonne, una per i dati statici notif e una come flag per lo stato, cioè "s: read" o "s: new" con 's 'come il cf e lo stato come il qualificatore. Ci sarebbe esattamente uno per riga, e posso fare un MultipleColumnPrefixFilter o SkipFilter w/ColumnPrefixFilter contro quel cf. Anche in questo caso, dovrei eliminare e creare colonne sul cambio di stato, ma dovrebbe essere molto più leggero rispetto alla copia di intere righe. La mia unica preoccupazione è l'avviso nel libro HBase che HBase non funziona bene con "più di 2 o 3 famiglie di colonne" - forse se il sistema deve essere esteso con più capacità di interrogazione, la strategia multi-cf non verrà ridimensionata .
Quindi (1) sembra che ci sarebbe troppo sovraccarico di rete. (2) sembra che avrebbe sprecato i costi spesi per copiare i dati e (3) potrebbe causare problemi con troppe famiglie. Tra (2) e (3), quale tipo di filtro dovrebbe fornire prestazioni migliori? In entrambi i casi, la scansione esaminerà ciascuna riga per un utente, che presumibilmente ha in gran parte le notifiche di lettura, il che avrebbe prestazioni migliori. Penso di essere inclinato verso (3) - ci sono altre opzioni (o ritocchi) che mi sono perso?
Gli stati di notifica "nuovi" e "letti" solo con una singola transizione possibile da nuovo a letto? Qual è il volume di queste notifiche? – Gevorg