2011-01-06 17 views
8

Esiste un modo efficace per eliminare più righe in HBase o il mio caso d'uso non sembra adatto per HBase?Modo efficiente per eliminare più righe in HBase

C'è una tabella che dice 'grafico', che contiene elementi che sono nei grafici. chiavi Row sono nel seguente formato: chart|date_reversed|ranked_attribute_value_reversed|content_id

volte vorrei per rigenerare grafico per una determinata data, quindi voglio eliminare tutte le righe a partire dal 'chart | date_reversed_1' fino a 'chart | date_reversed_2'. C'è un modo migliore rispetto a quello di emettere un Elimina per ogni riga trovata da una scansione? Tutte le righe da eliminare saranno vicine l'una all'altra.

Ho bisogno di cancellare le righe, perché non voglio che un elemento (un content_id) abbia più voci che avrà se il suo valore rank_attributo è stato modificato (il suo cambiamento è il motivo per cui il grafico deve essere rigenerato) .

Essendo un principiante HBase, quindi forse potrei fare un uso scorretto di righe per qualcosa che le colonne sarebbero migliori - se hai un suggerimento di design, cool! Oppure, forse i grafici sono meglio generati in un file (ad esempio non HBase per l'output)? Sto usando MapReduce.

risposta

7

In primo luogo, arrivando al punto di eliminazione intervallo non è ancora stato eliminato l'intervallo in HBase, AFAIK. Ma c'è un modo per cancellare più di una riga alla volta nello HTableInterface API. Per fare ciò basta formare un oggetto Elimina con le chiavi di riga dalla scansione e inserirli in un elenco e utilizzare l'API, fatto! Per rendere più rapida la scansione, non includere alcuna famiglia di colonne nel risultato della scansione, poiché tutto ciò di cui hai bisogno è la chiave di riga per l'eliminazione di intere righe.

In secondo luogo, sul design. Innanzitutto la mia comprensione del requisito è, ci sono contenuti con id di contenuto e ogni contenuto ha grafici generati contro di loro e quei dati sono memorizzati; ci possono essere più grafici per contenuto tramite date e dipende dal grado. Inoltre, vogliamo che l'ultimo grafico del contenuto generato sia visualizzato nella parte superiore della tabella.

Per la mia ipotesi del requisito, suggerirei di utilizzare tre tabelle: auto_id, content_charts e generate_order. La chiave di riga per content_charts sarebbe il suo ID di contenuto e la chiave di riga per generato_order sarebbe lunga, ovvero con decremento automatico utilizzando HTableInterface API. Per il decremento usa "-1" come importo da compensare e inizializzare il valore Long.MAX_VALUE nella tabella auto_id al primo avvio dell'app o manualmente. Quindi ora se vuoi cancellare i dati del grafico, semplicemente pulisci la famiglia di colonne usando delete e poi rimetti i nuovi dati e poi inserisci la tabella generate_order. In questo modo l'ultimo inserimento sarà anche in cima all'ultima tabella di inserimento che manterrà l'id del contenuto come un valore di cella. Se vuoi assicurarti che generated_order abbia solo una voce per contenuto, salva prima l'ID generato_destinato e prendi il valore e salvalo in content_charts quando inserisci e prima di eliminare la famiglia di colonne prima cancella la riga da generato_order. In questo modo è possibile cercare e grafici per un contenuto utilizzando 2 ottiene al massimo e nessuna scansione richiesta per i grafici.

Spero che questo sia utile.

2

È possibile utilizzare BulkDeleteProtocol che utilizza una scansione che definisce l'intervallo pertinente (riga iniziale, riga finale, filtri).

Vedi here

+1

Questo oggetto non è incluso nel 96 – Adelin

2

ho incontrato la vostra situazione e questo è il mio codice per implementare ciò che si vuole

Scan scan = new Scan(); 
    scan.addFamily("Family"); 
    scan.setStartRow(structuredKeyMaker.key(starDate)); 
    scan.setStopRow(structuredKeyMaker.key(endDate + 1)); 
try { 
    ResultScanner scanner = table.getScanner(scan); 


    Iterator<Entity> cdrIterator = new EntityIteratorWrapper(scanner.iterator(), EntityMapper.create(); // this is a simple iterator that maps rows to exact entity of mine, not so important ! 

    List<Delete> deletes = new ArrayList<Delete>(); 
    int bufferSize = 10000000; // this is needed so I don't run out of memory as I have a huge amount of data ! so this is a simple in memory buffer 
    int counter = 0; 
    while (entityIterator.hasNext()) { 
     if (counter < bufferSize) { 
          // key maker is used to extract key as byte[] from my entity 
      deletes.add(new Delete(KeyMaker.key(entityIterator.next()))); 
      counter++; 

     } else { 
      table.delete(deletes); 
      deletes.clear(); 
      counter = 0; 
     } 
    } 

    if (deletes.size() > 0) { 
     table.delete(deletes); 
     deletes.clear(); 
    } 

} catch (IOException e) { 
    e.printStackTrace(); 
} 
Problemi correlati