我有一些来自Common Crawl的mapred数据,我已经以SequenceFile格式存储了这些数据。我已经多次尝试使用Hive“按原样”使用这些数据,因此我可以在各个阶段查询和采样。但是我的工作输出总是出现以下错误:
LazySimpleSerDe: expects either BytesWritable or Text object!
我甚至构建了一个更简单(和更小)的[Text,LongWritable]记录数据集,但也失败了。如果我将数据输出为文本格式,然后在其上创建一个表,它可以正常工作:
hive> create external table page_urls_1346823845675
> (pageurl string, xcount bigint)
> location 's3://mybucket/text-parse/1346823845675/';
OK
Time taken: 0.434 seconds
hive> select * from page_urls_1346823845675 limit 10;
OK
http://0-italy.com/tag/package-deals 643 NULL
http://011.hebiichigo.com/d63e83abff92df5f5913827798251276/d1ca3aaf52b41acd68ebb3bf69079bd1.html 9 NULL
http://01fishing.com/fly-fishing-knots/ 3437 NULL
http://01fishing.com/flyin-slab-creek/ 1005 NULL
...
我尝试使用自定义inputformat:
// My custom input class--very simple
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.SequenceFileInputFormat;
public class UrlXCountDataInputFormat extends
SequenceFileInputFormat<Text, LongWritable> { }
然后用:
创建表格create external table page_urls_1346823845675_seq
(pageurl string, xcount bigint)
stored as inputformat 'my.package.io.UrlXCountDataInputFormat'
outputformat 'org.apache.hadoop.mapred.SequenceFileOutputFormat'
location 's3://mybucket/seq-parse/1346823845675/';
但我仍然得到相同的SerDer错误。
我确信这里有一些非常基本的东西,但我似乎无法做到这一点。另外,我必须能够解析SequenceFiles(即我无法将数据转换为文本)。因此,我需要为项目的未来部分找出SequenceFile方法。
解决方案: 正如@ mark-grover在下面指出的那样,问题是Hive默认忽略了密钥。只有一列(即只是值),serder无法映射我的第二列。
解决方案是使用比我原先使用的更复杂的自定义InputFormat。我在链接到Git时找到了一个关于使用键而不是值的答案,然后我修改它以满足我的需要:从内部SequenceFile.Reader获取键和值,然后将它们组合到最终的BytesWritable中。即像这样的东西(来自自定义阅读器,因为那是所有艰苦工作发生的地方):
// I used generics so I can use this all with
// other output files with just a small amount
// of additional code ...
public abstract class HiveKeyValueSequenceFileReader<K,V> implements RecordReader<K, BytesWritable> {
public synchronized boolean next(K key, BytesWritable value) throws IOException {
if (!more) return false;
long pos = in.getPosition();
V trueValue = (V) ReflectionUtils.newInstance(in.getValueClass(), conf);
boolean remaining = in.next((Writable)key, (Writable)trueValue);
if (remaining) combineKeyValue(key, trueValue, value);
if (pos >= end && in.syncSeen()) {
more = false;
} else {
more = remaining;
}
return more;
}
protected abstract void combineKeyValue(K key, V trueValue, BytesWritable newValue);
}
// from my final implementation
public class UrlXCountDataReader extends HiveKeyValueSequenceFileReader<Text,LongWritable>
@Override
protected void combineKeyValue(Text key, LongWritable trueValue, BytesWritable newValue) {
// TODO I think we need to use straight bytes--I'm not sure this works?
StringBuilder builder = new StringBuilder();
builder.append(key);
builder.append('\001');
builder.append(trueValue.get());
newValue.set(new BytesWritable(builder.toString().getBytes()) );
}
}
有了这个,我得到了所有的专栏!
http://0-italy.com/tag/package-deals 643
http://011.hebiichigo.com/d63e83abff92df5f5913827798251276/d1ca3aaf52b41acd68ebb3bf69079bd1.html 9
http://01fishing.com/fly-fishing-knots/ 3437
http://01fishing.com/flyin-slab-creek/ 1005
http://01fishing.com/pflueger-1195x-automatic-fly-reels/ 1999
答案 0 :(得分:0)
不确定这是否会影响您,但Hive会在读取SequenceFiles时忽略键。您可能需要创建一个自定义的InputFormat(除非您可以在线找到一个: - ))