【发布时间】:2013-08-14 10:31:56
【问题描述】:
我通过 AWS EMR 运行 Hive,并且有一个经常将日志数据解析到 S3 的工作流。我对已解析的 Hive 表使用动态分区(日期和日志级别)。
当我有几 GB 的数据和很多分区时,现在需要永远做的一件事是 Hive 在解析完成后将数据加载到表中。
Loading data to table default.logs partition (dt=null, level=null)
...
Loading partition {dt=2013-08-06, level=INFO}
Loading partition {dt=2013-03-12, level=ERROR}
Loading partition {dt=2013-08-03, level=WARN}
Loading partition {dt=2013-07-08, level=INFO}
Loading partition {dt=2013-08-03, level=ERROR}
...
Partition default.logs{dt=2013-03-05, level=INFO} stats: [num_files: 1, num_rows: 0, total_size: 1905, raw_data_size: 0]
Partition default.logs{dt=2013-03-06, level=ERROR} stats: [num_files: 1, num_rows: 0, total_size: 4338, raw_data_size: 0]
Partition default.logs{dt=2013-03-06, level=INFO} stats: [num_files: 1, num_rows: 0, total_size: 828250, raw_data_size: 0]
...
Partition default.logs{dt=2013-08-14, level=INFO} stats: [num_files: 5, num_rows: 0, total_size: 626629, raw_data_size: 0]
Partition default.logs{dt=2013-08-14, level=WARN} stats: [num_files: 4, num_rows: 0, total_size: 4405, raw_data_size: 0]
有没有办法克服这个问题并减少这一步的加载时间?
我已经尝试通过存储桶生命周期规则将旧日志存档到 Glacier,希望 Hive 会跳过加载存档分区。好吧,因为这仍然保持文件(路径)在 S3 Hive 中可见,所以无论如何都可以识别存档分区,因此不会获得任何性能。
更新 1
数据的加载是通过简单地将数据插入到动态分区表中来完成的
INSERT INTO TABLE logs PARTITION (dt, level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, dt, level
FROM new_logs ;
来自一个包含未解析日志的表
CREATE EXTERNAL TABLE new_logs (
dt STRING,
time STRING,
thread STRING,
level STRING,
logger STRING,
identity STRING,
message STRING,
logtype STRING,
logsubtype STRING,
node STRING,
storageallocationstatus STRING,
nodelist STRING,
userid STRING,
nodeid STRING,
path STRING,
datablockid STRING,
hash STRING,
size STRING,
value STRING,
exception STRING,
version STRING
)
PARTITIONED BY (
server STRING,
app STRING
)
ROW FORMAT
DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS
INPUTFORMAT 'org.maz.hadoop.mapred.LogFileInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat'
LOCATION 's3://my-log/logs/${LOCATION}' ;
进入新的(已解析的)表
CREATE EXTERNAL TABLE logs (
time STRING,
thread STRING,
logger STRING,
identity STRING,
message STRING,
logtype STRING,
logsubtype STRING,
node STRING,
storageallocationstatus STRING,
nodelist STRING,
userid STRING,
nodeid STRING,
path STRING,
datablockid STRING,
hash STRING,
size STRING,
exception STRING,
value STRING,
server STRING,
app STRING,
version STRING
)
PARTITIONED BY (
dt STRING,
level STRING
)
ROW FORMAT
DELIMITED
FIELDS TERMINATED BY '\t'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION 's3://my-log/parsed-logs' ;
输入格式(LogFileInputFormat)负责将日志条目解析为所需的日志格式。
更新 2
当我尝试以下操作时
INSERT INTO TABLE logs PARTITION (dt, level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, dt, level
FROM new_logs
WHERE dt > 'some old date';
Hive 仍然在日志中加载所有分区。另一方面,如果我使用静态分区,例如
INSERT INTO TABLE logs PARTITION (dt='some date', level)
SELECT time, thread, logger, identity, message, logtype, logsubtype, node, storageallocationstatus, nodelist, userid, nodeid, path, datablockid, hash, size, value, exception, server, app, version, level
FROM new_logs
WHERE dt = 'some date';
Hive 仅加载相关分区,但我需要为我认为可能出现在 new_logs 中的每个日期创建一个查询。通常 new_logs 仅包含今天和昨天的日志条目,但也可能包含较旧的条目。
静态分区是我目前选择的解决方案,但没有其他(更好的)解决方案可以解决我的问题吗?
【问题讨论】:
-
在插入过程中总共有多少个分区受到影响?从日志来看,似乎存在数据量非常小的分区(total_size) - 也许可以使用更大的(比如每月)分区?您究竟是如何加载数据的?
-
@dimamah 通常只有当前日期会受到插入过程的影响,因为当日志文件上传到 S3 时,我会立即对其进行解析。难道是因为我使用动态分区,Hive 不可能知道在插入过程中哪些分区会受到影响,因此会加载每个可用的分区?请参阅更新的部分。
-
hive 只会更新受影响的分区,这真的很奇怪,只有在您使用动态分区时才需要很长时间。究竟需要很长时间?映射器运行多长时间?减速机运行多长时间?如果有阶段,请说明每个阶段。是否有特定的映射器/减速器长时间运行?请粘贴它的日志。
标签: amazon-s3 hive amazon-emr