有选择地将iis日志文件加载到Hive中

时间:2013-08-19 21:46:42

标签: hadoop hive apache-pig hdfs

我刚刚开始使用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表中。

我有两个问题/问题:

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

如何将这些启用的字段映射到包含所有可能列的模式,为缺少的字段插入空白/空/ - 标记?这是我用Pig脚本处理的东西吗?

2

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

2 个答案:

答案 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(用户定义函数)解决我的两个问题

  1. 将列映射到正确的架构:请参阅此answer和此one
  2. 我真正需要做的就是添加一些逻辑来处理以#开头的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;
                    }
                }
                ...
             }
    
    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();
          }
      
    2. 然后在getNext()中我可以添加输出元组的路径。