0

我刚刚开始在 cloudera 平台上使用 Hadoop/Pig/Hive,并且对如何有效加载数据进行查询有疑问。

我目前有大约 50GB 的 iis 日志加载到 hdfs 中,目录结构如下:

/user/oi/raw_iis/Webserver1/Org/SubOrg/W3SVC1056242793/ /user/oi/raw_iis/Webserver2/Org/SubOrg/W3SVC1888303555/ /user/oi/raw_iis/Webserver3/Org/SubOrg/W3SVC1056245683/

ETC

我想将所有日志加载到 Hive 表中。

我有两个问题/疑问:

1.

我的第一个问题是一些网络服务器可能没有正确配置,并且将有没有所有列的 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

如何将这些启用的字段映射到包含所有可能列的架构,为丢失的字段插入空白/空/-令牌?这是我可以用猪脚本处理的吗?

2.

如何定义我的 Hive 表以包含来自 hdfs 路径的信息,即我的 dir 结构示例中的 Org 和 SubOrg,以便它可以在 Hive 中查询?我也不确定如何将许多目录中的数据正确导入到单个配置单元表中。

4

2 回答 2

0

首先提供示例数据以获得更好的帮助。

如何将这些启用的字段映射到包含所有可能列的架构,为丢失的字段插入空白/空/-令牌?

如果文件中有分隔符,则可以使用 Hive,并且 Hive 会在不存在数据的地方自动正确插入空值。前提是您没有将分隔符作为数据的一部分。

这是我可以用猪脚本处理的吗?

如果字段中有分隔符,则可以使用Hive,否则可以使用mapreduce/pig

如何在我的 dir 结构示例中包含来自 hdfs 路径的信息,即 Org 和 SubOrg,以便它可以在 Hive 中查询?

似乎您是蜂巢中的新蜜蜂,在查询之前您必须创建一个包含类似信息的表path,delimiter and schema

这是一个很好的分区候选者吗?

partition on date如果你愿意,你可以申请。

于 2013-08-20T06:39:33.120 回答
0

我能够用 Pig UDF(用户定义的函数)解决我的两个问题

  1. 将列映射到正确的架构:请参阅这个答案这个

我真正需要做的就是添加一些逻辑来处理以 # 开头的 iis 标头。下面是我使用的 getNext() 的片段,其他一切都与 mr2ert 的示例代码相同。

请参阅 values[0].equals("#Fields:") 部分。

        @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;
                }
            }
            ...
         }
  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() 中,我可以将路径添加到输出元组。

于 2013-08-23T18:59:10.197 回答