2015-11-10 15 views
5

Nel mio cantiere flusso di dati, sto impostando il campo impressions_raw come Long in un oggetto com.google.api.services.bigquery.model.TableRow:Dataflow miscelazione Integer e tipi lunghi

enter image description here

Più avanti nel mio cantiere, ho letto la TableRow indietro . Ma invece di un Long, torno a Integer.

enter image description here

Tuttavia, se ho impostato in modo esplicito il valore di essere un valore maggiore di LongInteger.MAX_VALUE, ad esempio 3 miliardi, poi torno a Long!

enter image description here enter image description here

Is sembra che il flusso di dati SDK sta facendo una sorta di ottimizzazione tipo di controllo sotto il cofano.

Quindi, senza fare il brutto tipo di controllo, come si dovrebbe affrontare questo con programmazione? (forse ho perso qualcosa di ovvio)

+0

Potresti postare parte del codice che crea, modifica e legge questi oggetti? – Nick

+0

Nick, ho pubblicato un esempio con una buona sintassi su: https://gist.github.com/dhalperi/9f13ab33eab59083dc1a#file-example-for-so-java –

risposta

3

Grazie per il rapporto. Sfortunatamente, questo problema è fondamentale con l'uso di TableRow. Si consiglia vivamente la soluzione 1 di seguito: convertire da TableRow non appena possibile nella propria pipeline.

L'oggetto TableRow in cui si memorizzano questi valori è serializzato e deserializzato da Jackson, all'interno di TableRowJsonCoder. Jackson ha esattamente il comportamento che stai descrivendo - che è, per questa classe:

class MyClass { 
    Object v; 
} 

che verrà serializzare un'istanza con v = Long.valueOf(<number>) come {v: 30} o {v: 3000000000}. In fase di deserializzazione, tuttavia, determinerà il tipo di oggetto utilizzando il numero di bit necessari per rappresentare la risposta. Vedi this SO post.

Due possibili soluzioni vengono in mente, con la soluzione 1 fortemente raccomandato:

  1. Non usare TableRow come un valore intermedio. In altre parole, converti in POJO il prima possibile. Il motivo principale per cui si verifica questo tipo di mixup è che TableRow è essenzialmente un Map<String, Object> e Jackson (o altri codificatori) non può sapere che si desidera un indietro. Con un POJO, i tipi sarebbero chiari.

    L'altro vantaggio dello spegnimento di TableRow consiste nel raggiungere un codificatore efficiente, ad esempio AvroCoder. Poiché TableRow s sono codificati e decodificati su/da JSON, la codifica è al tempo stesso prolissa e lenta - shuffling TableRow sarà sia intensiva per CPU che I/O. Prevedo che vedrete prestazioni molto migliori con POJO con codice Avro rispetto a quando passerete intorno agli oggetti TableRow.

    Per un esempio, vedere LaneInfo in TrafficMaxLaneFlow.

  2. codice Scrivi in ​​grado di gestire entrambe le cose:

    long numberToLong(@Nonnull Number n) { 
        return n.longValue(); 
    } 
    long x = numberToLong((Number) row.get("field")); 
    
    Long numberToLong(@Nonnull Number n) { 
        if (n instanceof Long) { 
         // avoid a copy 
         return n; 
        } 
        return Long.valueOf(n.longValue()); 
    } 
    Long x = numberToLong((Number) row.get("field")); 
    

    potrebbe essere necessario controlli supplementari per la seconda variante, se n può essere null.

+1

Grazie @ Dan Halperin –

Problemi correlati