我有一堆存储在Amazon S3中的小型(1KB到1MB)文本文件,我想使用Amazon EMR的Hadoop进行处理。
给映射器的每条记录都需要包含文本文件的全部内容以及确定文件名的方法,所以我不能使用默认的TextInputFormat。
实现这一目标的最佳方法是什么?还有什么我可以做的(比如将文件从S3复制到hdfs)来提高性能吗?
答案 0 :(得分:0)
我有同样的问题。请参考以下问题。
如果您没有任何大文件但文件很多,则使用s3cmd get --recursive s3://<url> .
命令就足够了。在将文件检索到EMR实例后,您可以使用Hive创建表。例如,您可以使用带有分区的LOAD DATA
语句加载整个文件。
示例
这是一个示例代码
#!/bin/bash
s3cmd get --recursive s3://your.s3.name .
# create table with partitions
hive -e "SET mapred.input.dir.recursive=true; DROP TABLE IF EXISTS import_s3_data;"
hive -e "CREATE TABLE import_s3_data( rawdata string )
PARTITIONED BY (tier1 string, tier2, string, tier3 string);"
LOAD_SQL=""
# collect files as array
FILES=(`find . -name \*.txt -print`)
for FILE in ${FILES[@]}
do
DIR_INFO=(`echo ${FILE##./} | tr -s '/' ' '`)
T1=${DIR_INFO[0]}
T2=${DIR_INFO[1]}
T3=${DIR_INFO[2]}
LOAD_SQL="${LOAD_SQL} LOAD DATA LOCAL INPATH '${FILE}' INTO TABLE
import_s3_data PARTITION (tier1 = '${T1}', tier2 = '${T2}', tier3 = '${T3}');"
done
hive -e "${LOAD_SQL}"
另一个选项
我认为还有一些其他方法可以检索小型S3数据
s3cmd get
的情况相比,它具有几乎相同的性能。在这种情况下它可能更有效,S3上有许多大的原始或gziped文件。答案 1 :(得分:0)
对我来说,最好的方法是在CSV文件上创建一个external table
并将其加载到另一个以S3
格式存储在parquet
存储桶中的表中。在这种情况下,您将不必编写任何脚本,只需编写几个SQL查询即可。
CREATE EXTERNAL TABLE databasename.CSV_EXT_Module(
recordType BIGINT,
servedIMSI BIGINT,
ggsnAddress STRING,
chargingID BIGINT,
...
...
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
LOCATION 's3://module/input/csv_files/'
TBLPROPERTIES ("skip.header.line.count"="1");
上表仅是映射到csv文件的外部表。
如果要使查询运行更快,请在该表的顶部创建另一个表:
CREATE TABLE databasename.RAW_Module as
SELECT
recordType,
servedIMSI,
ggsnAddress,
chargingID,
...
regexp_extract(INPUT__FILE__NAME,'(.*)/(.*)',2) as filename from
databasename.CSV_EXT_Module
STORED AS PARQUET
LOCATION 's3://module/raw/parquet_files/';
更改regexp_extract以具有所需的输入文件名。