2015-10-19 12 views
5

Impostazione:

Ho una tabella HBase, con 100M + righe e 1 milione + colonne. Ogni riga contiene dati solo da 2 a 5 colonne. C'è in solo 1 famiglia di colonne.Possiamo ottenere tutti i nomi di colonna da una tabella HBase?

Problema:

voglio scoprire tutti i distinti qualifiers (colonne) in questo column family. C'è un modo rapido per farlo?

Posso pensare di eseguire la scansione dell'intero tavolo, quindi ottenere familyMap per ogni riga, ottenere qualifier e aggiungerlo a un Set<>. Ma sarebbe terribilmente lento, dato che ci sono 100 milioni di righe.

Possiamo fare di meglio?

risposta

1

HBase può essere visualizzato come una distribuito NavigableMap<byte[], NavigableMap<byte[], NavigableMap<byte[], NavigableMap<Long, byte[]>>>>

Non v'è alcun "metadati" (dire qualcosa memorizzate centralmente nel nodo master) circa l'elenco di tutte le gare di qualificazione che è disponibile in tutti i server regione.

Quindi, se si dispone di un caso di utilizzo una tantum, l'unico modo per voi sarebbe quello di eseguire la scansione dell'intera tabella e aggiungere i nomi dei qualificatori in un Set<>, come accennato.

Se si tratta di un caso d'uso ripetuto (in più se si ha la discrezione di aggiungere componenti allo stack tecnologico), si potrebbe voler considerare l'aggiunta di Redis. È possibile mantenere un set di qualificatori in modo distribuito utilizzando Redis Set.

0

I coprocessori HBase possono essere utilizzati per questo scenario. È possibile scrivere un'implementazione personalizzata di EndPoint che funziona come stored procedure in RDBMS. Esegue il codice sul lato server e ottiene colonne distinte per ogni regione. Sul client è possibile ottenere le colonne distinte in tutte le regioni.

Vantaggio prestazioni: Tutte le colonne non vengono trasferite al client, il che si traduce in chiamate di rete ridotte.

2

È possibile utilizzare una mappa per questo. In questo caso non è necessario installare una librerie personalizzata per hbase come nel caso del coprocessore. Sotto un codice per la creazione di un'attività mapreduce.

impostazione lavoro

Job job = Job.getInstance(config); 
    job.setJobName("Distinct columns"); 

    Scan scan = new Scan(); 
    scan.setBatch(500); 
    scan.addFamily(YOU_COLUMN_FAMILY_NAME); 
    scan.setFilter(new KeyOnlyFilter()); //scan only key part of KeyValue (raw, column family, column) 
    scan.setCacheBlocks(false); // don't set to true for MR jobs 


    TableMapReduceUtil.initTableMapperJob(
      YOU_TABLE_NAME, 
      scan,   
      OnlyColumnNameMapper.class, // mapper 
      Text.class,    // mapper output key 
      Text.class,    // mapper output value 
      job); 

    job.setNumReduceTasks(1); 
    job.setReducerClass(OnlyColumnNameReducer.class); 
    job.setReducerClass(OnlyColumnNameReducer.class); 

Mapper

public class OnlyColumnNameMapper extends TableMapper<Text, Text> { 
    @Override 
    protected void map(ImmutableBytesWritable key, Result value, final Context context) throws IOException, InterruptedException { 
     CellScanner cellScanner = value.cellScanner(); 
     while (cellScanner.advance()) { 

      Cell cell = cellScanner.current(); 
      byte[] q = Bytes.copy(cell.getQualifierArray(), 
           cell.getQualifierOffset(), 
           cell.getQualifierLength()); 

      context.write(new Text(q),new Text()); 

     } 
} 

}

Reducer

public class OnlyColumnNameReducer extends Reducer<Text, Text, Text, Text> { 

    @Override 
    protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {  
      context.write(new Text(key), new Text());  
    } 
} 
Problemi correlati