当创建的蜂巢外部表可我点目录中的位置,以特定的文件?当创建的蜂巢外部表可我点目录中的位置,以特定的文

2019-06-14 10:19发布

我已经定义了一个表作为这样的:

create external table PageViews (Userid string, Page_View string)
partitioned by (ds string)
row format as delimited fields terminated by ','
stored as textfile location '/user/data';

我不想在/用户/数据目录中的所有文件用作表的一部分。 是否有可能为我做到以下几点?

location 'user/data/*.csv'

Answer 1:

我碰到这个线程来到时,我有一个类似的问题来解决。 我能够通过使用自定义SERDE来解决它。 然后,我添加了引导什么的正则表达式应用到文件名模式对于任何特定的表SERDE特性。

自定义SERDE似乎矫枉过正,如果你只处理标准的CSV文件,我有一个更复杂的文件格式来处理。 不过这是一个非常可行的解决方案,如果你不从编写一些Java避而远之。 当您无法重组在存储位置的数据,你正在寻找一个不成比例的大文件组中一个非常特殊的文件模式是特别有用。

> CREATE EXTERNAL TABLE PageViews (Userid string, Page_View string)  
> ROW FORMAT SERDE 'com.something.MySimpleSerDe' 
> WITH SERDEPROPERTIES ( "input.regex" = "*.csv")
> LOCATION '/user/data';


Answer 2:

什么kmosley说的是真的。 截至目前,不能有选择性地选择某些文件是你的蜂巢表的一部分。 不过,也有2种方式来解决它。

选项1:可以将所有的CSV文件移动到另一个目录HDFS和最重要的是建立一个蜂巢表。 如果你工作得更好,你可以创建一个容纳所有CSV文件的子目录(比如,CSV)你现在的目录中。 然后,您可以在这个子目录的顶部创建一个蜂巢表。 请记住,在父目录之上创建的任何配置单元表将不包含从子目录中的数据。

选项2:您可以更改您的查询,使用称为虚拟列的INPUT__FILE__NAME

您的查询看起来是这样的:

SELECT 
   *
FROM
   my_table
WHERE
   INPUT__FILE__NAME LIKE '%csv';

这种做法的不良影响是,蜂巢查询将不得不通过整个数据目录中存在的流失,即使你只关心特定文件。 基于使用谓词的查询不会过滤掉的文件INPUT__FILE__NAME 。 它只会过滤掉不是来自比赛记录使用谓词INPUT__FILE__NAME在映射阶段(从而过滤掉从特定文件中的所有记录),但映射器将在不必要的文件上运行。 它会给你正确的结果,可能有一些,可能是次要的,性能开销。

这种方法的好处是,你可以使用相同的配置单元表,如果你有在你的表中的多个文件,你在几个疑问想从该表中查询所有文件的能力(或分区)和文件的一个子集其他查询。 你可以利用的INPUT__FILE__NAME虚拟列来实现这一目标。 举个例子:如果你的HDFS目录分区/user/hive/warehouse/web_logs/样子:

/user/hive/warehouse/web_logs/dt=2012-06-30/
   /user/hive/warehouse/web_logs/dt=2012-06-30/00.log
   /user/hive/warehouse/web_logs/dt=2012-06-30/01.log
   .
   .
   .
   /user/hive/warehouse/web_logs/dt=2012-06-30/23.log

比方说,你的表定义看起来像:

CREATE EXTERNAL TABLE IF NOT EXISTS web_logs_table (col1 STRING)
PARTITIONED BY (dt STRING)
LOCATION '/user/hive/warehouse/web_logs';

加入适当的分区后,你可以查询在使用类似的查询分区中的所有日志:

SELECT
   *
FROM
   web_logs_table w
WHERE
   dt='2012-06-30';

不过,如果你只关心从当天的第一个小时的记录,可以查询使用像查询的第一个小时的日志:

SELECT
   *
FROM
   web_logs_table w
WHERE 
   dt ='2012-06-30'
   AND INPUT__FILE__NAME='00.log';

另一个类似的用例可能是包含不同领域和各种查询网络日志需要分析不同组域日志的目录。 这些查询可以滤除使用域INPUT__FILE__NAME虚拟列。

在上述两种使用情况,其具有用于小时或域的子分区可以解决这个问题为好,而不必使用虚拟列。 然而,可能存在需要您不能创建子分区一些设计权衡。 在这种情况下,可以说,使用INPUT__FILE__NAME虚拟列是你最好的选择。

在2个选项之间作出决定:

这真的取决于你的使用情况。 如果你从来不计较这些文件是你正试图从蜂巢表排除,使用选项2可能是矫枉过正,你应该修复的目录结构和包含您关心文件的目录之上创建一个蜂巢表。

如果您目前不包括文件遵循相同的格式的其他文件(这样他们就可以全部是相同的蜂巢表的一部分),你可以看到自己写的查询,将分析目录中的所有数据,然后用期权去2。



Answer 3:

没有您目前无法做到这一点。 有一个JIRA票开放,允许包含文件的正则表达式选择的蜂巢表( https://issues.apache.org/jira/browse/HIVE-951 )。

现在最好的办法是在不同的目录下创建一个表,只是你要查询的文件复制。



文章来源: When creating an external table in hive can I point the location to specific files in a directory?
标签: hive external