2013-03-07 32 views
10

我有以HDFS文本形式存储的日志文件。当我将日志文件加载到Hive表中时,所有文件都被复制。是否可以在不复制数据的情况下将数据导入Hive表中

我可以避免将所有文本数据存储两次吗?

编辑:我通过以下命令加载它

LOAD DATA INPATH '/user/logs/mylogfile' INTO TABLE `sandbox.test` PARTITION (day='20130221') 

然后,我能找到完全相同的文件中:

/user/hive/warehouse/sandbox.db/test/day=20130220 

我以为它被复制。

+0

How do you say,它的复制?你如何将它们加载到配置单元表中? – 2013-03-07 12:26:12

+0

我通过'LOAD DATA INPATH'xxx'INTO TABLE yyy'(见文章编辑)加载它,然后在'/ user/hive/warehouse'中找到该文件。我想知道它是否可以离开它(我想我将不得不在我的目录中强制执行分区结构,但这很好) – 2013-03-07 13:11:39

+0

它如何存储在HDFS中? – 2013-03-07 13:12:08

回答

14

使用外部表:

CREATE EXTERNAL TABLE sandbox.test(id BIGINT, name STRING) ROW FORMAT 
       DELIMITED FIELDS TERMINATED BY ',' 
       LINES TERMINATED BY '\n' 
       STORED AS TEXTFILE 
       LOCATION '/user/logs/'; 

,如果你想使用分区与外部表,你将负责管理该分区的目录。 指定的位置必须是hdfs目录..

如果删除外部表格配置单元不会删除源数据。 如果想要管理你的原始文件,请使用外部表格。如果您希望配置单元执行此操作,请将仓库路径中的配置单元存储。

+0

正是我在找的东西!谢谢 – 2013-03-08 09:25:12

3

我可以说,不是将你的Java应用程序直接将数据复制到HDFS,而是将这些文件放在本地文件系统中,然后使用以下命令通过配置单元将它们导入HDFS。

LOAD DATA LOCAL INPATH '/your/local/filesystem/file.csv' INTO TABLE `sandbox.test` PARTITION (day='20130221') 

通知的LOCAL

+0

谢谢,这确实会起作用。另一个(效率较低)选项是删除原始文件。那么我想答案是:不,你不能告诉配置单元将数据保留在原来的位置,只是假设它是一个表格。由于这些文件非常大,因此Java应用程序通过Hadoop库直接写入HDFS。我可以用Java to Hive连接器做同样的事情吗?或者,如果我通过HDFS API写入适当的hive目录,Hive会认为它是数据文件吗? – 2013-03-07 13:44:16

+1

关于最后一部分。是的,如果你将文件直接放在HIVE仓库中,日期将在HIVE中可用,请记住从表格的定义中适合文件夹结构(http://stackoverflow.com/questions/15077046/using-multiple-levels-of- partition-in-hive/15102064#15102064) – www 2013-03-07 14:33:58

0

您可以使用alter table分区语句来避免数据重复。

create External table if not exists TestTable (testcol string) PARTITIONED BY (year INT,month INT,day INT) row format delimited fields terminated by ','; 

ALTER table TestTable partition (year='2014',month='2',day='17') location 'hdfs://localhost:8020/data/2014/2/17/'; 
0

Hive(至少当以真正集群模式运行时)不能引用本地文件系统中的外部文件。 Hive可以在表创建或加载操作期间自动导入文件。这背后的原因可能是Hive在内部运行MapReduce作业来提取数据。 MapReduce从HDFS中读取并写回到HDFS,甚至在分布式模式下运行。因此,如果文件存储在本地文件系统中,则分布式基础架构不能使用它。

相关问题