2016-03-02 2 views
1
.

. Я пытаюсь сериализовать данные csv в формате Паркет, используя схему Avro (Avro Backed) &, снова считывая это в таблицы улья.ClassCastException при де-сериализации (загрузка в таблицу улей) десятичные знаки, записанные в архитектуре avro. Формат паркета.

Это успешно получать сериализовать, используя следующий пример фрагмента кода (Пример кода для сериализации одну единственную запись):

import java.io.File; 
import java.io.IOException; 
import java.math.BigDecimal; 
import java.math.BigInteger; 
import java.nio.ByteBuffer; 

import org.apache.avro.Schema; 
import org.apache.avro.generic.GenericData; 
import org.apache.avro.generic.GenericData.Record; 
import org.apache.avro.generic.GenericRecord; 
import org.apache.hadoop.fs.Path; 
import org.apache.parquet.avro.AvroSchemaConverter; 
import org.apache.parquet.avro.AvroWriteSupport; 
import org.apache.parquet.hadoop.ParquetWriter; 
import org.apache.parquet.hadoop.metadata.CompressionCodecName; 
import org.apache.parquet.schema.MesspidType; 

public class AvroParquetConverter { 

    public static void main(String[] args) throws IOException { 
     Schema avroSchema = new Schema.Parser().parse(new File("schema.avsc")); 
     GenericRecord myrecord = new GenericData.Record(avroSchema); 
     String outputFilename = "/home/jai/sample1000-snappy.parquet"; 
     Path outputPath = new Path(outputFilename); 
     MesspidType parquetSchema = new AvroSchemaConverter() 
       .convert(avroSchema); 
     AvroWriteSupport writeSupport = new AvroWriteSupport(parquetSchema, 
       avroSchema); 
     CompressionCodecName compressionCodecSnappy = CompressionCodecName.SNAPPY; 
     int blockSize = 256 * 1024 * 1024; 
     int ppidSize = 64 * 1024; 

     ParquetWriter parquetWriterSnappy = new ParquetWriter(outputPath, 
       writeSupport, compressionCodecSnappy, blockSize, ppidSize); 
     BigDecimal bd = new BigDecimal(20); 
     GenericRecord myrecordTemp = new GenericData.Record(avroSchema); 
     myrecord.put("name", "Abhijeet1"); 
     myrecord.put("pid", 20); 
     myrecord.put("favorite_number", 22); 
     String bd1 = "13.5"; 
     BigDecimal bdecimal = new BigDecimal(bd1); 
     bdecimal.setScale(15, 6); 
     BigInteger bi = bdecimal.unscaledValue(); 
     byte[] barray = bi.toByteArray(); 
     ByteBuffer byteBuffer = ByteBuffer.allocate(barray.length); 
     byteBuffer.put(barray); 
     byteBuffer.rewind(); 
     myrecord.put("price", byteBuffer); 
     parquetWriterSnappy.write(myrecord); 
     parquetWriterSnappy.close(); 
    } 
} 

Пробовал десятичную в ByteBuffer преобразование осуществляется с помощью следующее заявление, а также:

ByteBuffer.wrap(bdecimal.unscaledValue().toByteArray()); 

Ниже приведено описание файла схемы avro

{ 
    "namespace": "avropoc", 
    "type": "record", 
    "name": "User", 
    "fields": [ 
      {"name": "name", "type": "string", "default" : "null"}, 
      {"name": "favorite_number", "type": "int", "default": 0 }, 
      {"name": "pid", "type":"int", "default" : 0 }, 
      {"name": "price", "type": {"type" : "bytes","logicalType":"decimal","precision":15,"scale":6}, "default" : 0 } 
    ] 
} 

также попытались следующие модификации и схемы:

{"name": "price", "type": "bytes","logicalType":"decimal","precision":15,"scale":6, "default" : 0 } 

И я создаю улую таблицу следующим образом:

create external table avroparquet1 
(name string, favorite_number int, 
pid int, price DECIMAL(15,6)) 
STORED AS PARQUET; 

Но когда я бег запроса для десятичной цены поля я получаю следующее сообщение об ошибке:

Failed с исключением java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException: java.lang.ClassCastException: org.apache.hadoop.i o.BytesWritable не может быть приведен к org.apache.hadoop.hive.serde2.io.HiveDecimalWritable

Это выглядит как паркет/Avro проблема, связанная/улей, где он не в состоянии десериализации Decimals, который в случае AVRO должен быть написан как ByteBuffer.

Я пробовал это на avro 1.8.0, паркет 1.8.1 & Hive 1.1.0.

Любая помощь будет оценена по достоинству.

ответ

0

Фактическая схема генерируется Улей для DECIMAL (22,7) - с помощью какой-то код, полученный из that LinkedIn utility для проверки фактических Паркетные файлов - выглядит как ...

  • Паркет Синтаксис: optional fixed_len_byte_array(10) my_dec_22_7;
  • AVRO синтаксис: { "name":"my_dec_22_7","type":["null",{"type":"fixed", "name":"my_dec_22_7","size":10} ], "default":null }

... где 10-видимому, количество байтов, необходимых для дампа BigInteger с 22 цифрами в byte[]. Посмотрите на исходный код AvroSerdeUtils и как он сбрасывает HiveDecimal, например.

Это, как говорится, я действительно не знаю, как читать/писать DECIMAL в файле Parquet. DOUBLE и BIGINT намного легче обрабатывать, поскольку они поддерживаются стандартными типами IEEE (и стандартными типами AVRO, и стандартными типами Паркета).

 Смежные вопросы

  • Нет связанных вопросов^_^