我刚刚开始使用cloudera平台上的Hadoop / Pig / Hive,并对如何有效加载数据进行查询有疑问。
我目前有大约50GB的iis日志加载到hdfs中,具有以下目录结构:
/用户/ OI / raw_iis / Webserver1 /组织/ SubOrg / W3SVC1056242793 / /用户/ OI / raw_iis / Webserver2 /组织/ SubOrg / W3SVC1888303555 / /用户/ OI / raw_iis / Webserver3 /组织/ SubOrg / W3SVC1056245683 /
等
我想将所有日志加载到Hive表中。
我有两个问题/问题:
我的第一个问题是某些网络服务器可能没有正确配置,并且没有所有列的iis日志。这些不正确的日志需要进行额外的处理,以将日志中的可用列映射到包含所有列的模式。
数据是以空格分隔的,问题是当未启用所有列时,日志仅包括启用的列。 Hive无法自动插入空值,因为数据不包含空列。我需要能够将日志中的可用列映射到完整模式。
好日志示例:
#Fields: date time s-ip cs-method cs-uri-stem useragent
2013-07-16 00:00:00 10.1.15.8 GET /common/viewFile/1232 Mozilla/5.0+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/27.0.1453.116+Safari/537.36
缺少列的示例日志(cs-method和useragent):
#Fields: date time s-ip cs-uri-stem
2013-07-16 00:00:00 10.1.15.8 /common/viewFile/1232
需要将缺少列的日志映射到完整模式,如下所示:
#Fields: date time s-ip cs-method cs-uri-stem useragent
2013-07-16 00:00:00 10.1.15.8 null /common/viewFile/1232 null
如何将这些启用的字段映射到包含所有可能列的模式,为缺少的字段插入空白/空/ - 标记?这是我用Pig脚本处理的东西吗?
如何定义我的Hive表以包含来自hdfs路径的信息,即我的目录结构示例中的Org和SubOrg,以便它可以在Hive中查询?我也不确定如何将多个目录中的数据正确导入到单个hive表中。
答案 0 :(得分:0)
首先提供样本数据以获得更好的帮助。
如何将这些启用的字段映射到包含所有可能列的模式,为缺少的字段插入空白/空/ - 标记?
如果你在文件中有分隔符,你可以使用Hive和hive在数据不存在的地方自动正确地插入空值。提供你没有分隔符作为数据的一部分。
这是我可以使用Pig脚本处理的内容吗?
如果您在字段中有分隔符,则可以使用Hive
,否则您可以使用mapreduce/pig
。
如何在hdfs路径中包含信息,即我的目录结构示例中的Org和SubOrg,以便它可以在Hive中查询?
似乎你是蜂巢中的新蜜蜂,在查询之前你需要create a table,其中包括path,delimiter and schema
等信息。
这是否适合进行分区?
如果您愿意,可以申请partition on date
。
答案 1 :(得分:0)
我能够用Pig UDF(用户定义函数)解决我的两个问题
我真正需要做的就是添加一些逻辑来处理以#开头的iis头文件。以下是我使用的getNext()片段,其他一切与mr2ert的示例代码相同。
参见值[0] .equals(“#Fields:”)parts。
@Override
public Tuple getNext() throws IOException {
...
Tuple t = mTupleFactory.newTuple(1);
// ignore header lines except the field definitions
if(values[0].startsWith("#") && !values[0].equals("#Fields:")) {
return t;
}
ArrayList<String> tf = new ArrayList<String>();
int pos = 0;
for (int i = 0; i < values.length; i++) {
if (fieldHeaders == null || values[0].equals("#Fields:")) {
// grab field headers ignoring the #Fields: token at values[0]
if(i > 0) {
tf.add(values[i]);
}
fieldHeaders = tf;
} else {
readField(values[i], pos);
pos = pos + 1;
}
}
...
}
要包含文件路径中的信息,我将以下内容添加到我以前解决的LoadFunc UDF中1.在prepareToRead重写中,获取文件路径并将其存储在成员变量中。
public class IISLoader extends LoadFunc {
...
@Override
public void prepareToRead(RecordReader reader, PigSplit split) {
in = reader;
filePath = ((FileSplit)split.getWrappedSplit()).getPath().toString();
}
然后在getNext()中我可以添加输出元组的路径。