在hive中创建外部表时,我可以将位置指向目录中的特定文件吗?

Geo*_*lde 23 hive external

我已经定义了一个表:

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';
Run Code Online (Sandbox Code Playgroud)

我不希望/ user/data目录中的所有文件都用作表的一部分.我有可能做到以下几点吗?

location 'user/data/*.csv'
Run Code Online (Sandbox Code Playgroud)

小智 20

kmosley说的是真的.截至目前,您无法有选择地选择某些文件作为Hive表的一部分.但是,有两种方法可以解决它.

选项1: 您可以将所有csv文件移动到另一个HDFS目录中,并在其上创建一个Hive表.如果它对您更有效,您可以在当前目录中创建一个包含所有CSV文件的子目录(例如,csv).然后,您可以在此子目录的顶部创建Hive表.请记住,在父目录之上创建的任何Hive表都不包含子目录中的数据.

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

您的查询看起来像:

SELECT 
   *
FROM
   my_table
WHERE
   INPUT__FILE__NAME LIKE '%csv';
Run Code Online (Sandbox Code Playgroud)

这种方法的不良影响是,即使您只关心特定文件,Hive查询也必须浏览目录中存在的整个数据.查询不会根据使用的谓词过滤掉文件INPUT__FILE__NAME.它只会过滤掉INPUT__FILE__NAME在地图阶段使用的谓词不匹配的记录(从而过滤掉特定文件中的所有记录),但是映射器也会在不必要的文件上运行.它会给你正确的结果,可能有一些,可能是次要的性能开销.

这种方法的好处是,如果表中有多个文件,并且希望能够在一些查询和一些文件中查询该表(或其分区)中的所有文件,则可以使用相同的Hive表.其他疑问.您可以使用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
Run Code Online (Sandbox Code Playgroud)

假设你的表定义如下:

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

添加适当的分区后,您可以使用以下查询查询分区中的所有日志:

SELECT
   *
FROM
   web_logs_table w
WHERE
   dt='2012-06-30';
Run Code Online (Sandbox Code Playgroud)

但是,如果您只关注当天第一个小时的日志,则可以使用以下查询查询第一个小时的日志:

SELECT
   *
FROM
   web_logs_table w
WHERE 
   dt ='2012-06-30'
   AND INPUT__FILE__NAME='00.log';
Run Code Online (Sandbox Code Playgroud)

另一个类似的用例可以是包含来自不同域的Web日志的目录,并且各种查询需要分析不同域集上的日志.查询可以使用INPUT__FILE__NAME虚拟列过滤掉域.

在上述两种用例中,拥有小时或域的子分区也可以解决问题,而无需使用虚拟列.但是,可能存在一些需要您不创建子分区的设计权衡.在这种情况下,可以说,使用INPUT__FILE__NAME虚拟列是您最好的选择.

在两个选项之间做出决定:

这真的取决于你的用例.如果您从不关心文件是否正在尝试从Hive表中排除,使用选项2可能是一种过度杀伤,您应该修复目录结构并在包含您关心的文件的目录之上创建一个Hive表.

如果您当前排除的文件遵循与其他文件相同的格式(因此它们都可以是同一个Hive表的一部分),您可以看到自己编写的查询将分析目录中的所有数据,然后选择2.


NG *_*lgo 11

当我遇到类似的问题时,我遇到了这个问题.我能够通过使用自定义SerDe来解决它.然后我添加了SerDe属性,它引导了RegEx应用于任何特定表的文件名模式.

如果你只处理标准的CSV文件,那么自定义SerDe可能看起来有点过头了,我有一个更复杂的文件格式需要处理.如果你不回避编写一些Java,这仍然是一个非常可行的解决方案.当您无法重新构建存储位置中的数据并且在不成比例的大文件集中查找非常特定的文件模式时,它尤其有用.

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


kmo*_*ley 7

不,你现在不能这样做.有一个JIRA票据打开,允许正则表达式选择包含Hive表的文件(https://issues.apache.org/jira/browse/HIVE-951).

现在,您最好的办法是在不同的目录上创建一个表,然后复制您要查询的文件.