【发布时间】:2016-09-10 00:07:57
【问题描述】:
我正在一个 hive 查询中测试一个相当繁重的 rlike 函数。我想在将它应用到我的 TB+ 数据之前,我会先对一个子集进行测试。 完整查询是:
create table proxy_parsed_clean as
select
a.*,
case
when domainname rlike '.*:443$' then 1
else 0
end as used_https
from proxy_parsed a;
因为有这么多的数据,我写了一个查询(表面上)会针对一个子集进行操作:
select
case
when a.domainname rlike '.*:443$' then 1
else 0
end as used_https
from (select domainname from proxy_parsed limit 10) a;
不过,这似乎只需要 与第一个查询一样长。与其将外部查询应用于子集,不如将 case 语句应用于整个数据集和 then 限制。运行explain 证实了我的怀疑(注意limit 子句已移至查询末尾):
> explain select case when a.domainname rlike '.*:443$' then 1 else 0 end from (select domainname from proxy_parsed limit 10) a;
+---------------------------------------------------------------------------------------------------------------------+--+
| Explain |
+---------------------------------------------------------------------------------------------------------------------+--+
| STAGE DEPENDENCIES: |
| Stage-1 is a root stage |
| Stage-0 depends on stages: Stage-1 |
| |
| STAGE PLANS: |
| Stage: Stage-1 |
| Map Reduce |
| Map Operator Tree: |
| TableScan |
| alias: proxy_parsed |
| Statistics: Num rows: 157462377267 Data size: 6298495090688 Basic stats: COMPLETE Column stats: NONE |
| Select Operator |
| expressions: domainname (type: varchar(40)) |
| outputColumnNames: _col0 |
| Statistics: Num rows: 157462377267 Data size: 6298495090688 Basic stats: COMPLETE Column stats: NONE |
| Limit |
| Number of rows: 10 |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| Reduce Output Operator |
| sort order: |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| TopN Hash Memory Usage: 0.1 |
| value expressions: _col0 (type: varchar(40)) |
| Reduce Operator Tree: |
| Select Operator |
| expressions: VALUE._col0 (type: varchar(40)) |
| outputColumnNames: _col0 |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| Limit |
| Number of rows: 10 |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| Select Operator |
| expressions: CASE WHEN ((_col0 rlike '.*:443$')) THEN (1) ELSE (0) END (type: int) |
| outputColumnNames: _col0 |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| File Output Operator |
| compressed: false |
| Statistics: Num rows: 10 Data size: 400 Basic stats: COMPLETE Column stats: NONE |
| table: |
| input format: org.apache.hadoop.mapred.TextInputFormat |
| output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat |
| serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe |
| |
| Stage: Stage-0 |
| Fetch Operator |
| limit: -1 |
| Processor Tree: |
| ListSink |
| |
+---------------------------------------------------------------------------------------------------------------------+--+
如果我只是运行select * from proxy_parsed limit 10;,查询执行得非常快。有人可以解释A),为什么查询没有在子集上执行,以及B)如何使它这样做?
我可以创建一个临时表,在其中选择 10 条记录,然后执行查询,但这似乎很草率。另外,在那之后我会有一个临时表来清理。这种行为似乎是一个 Hive 错误,即 limit 行为显然不像在这种情况下应该表现的那样。
【问题讨论】:
-
不是一个真正的答案,但也许这与限制声明有关,它没有保证它将返回哪些记录?
-
这也是我的好奇心......但通常在子查询中,外部查询将对(嵌套的)选定内容进行操作,因此内部选择(至少直观地)是有意义的只会返回 10 个随机行,外部查询将在这些行上运行。至少,我是这么认为的……似乎找不到任何解释
-
我不确定您的
select *示例是否生成了正确的 MapReduce 作业——Hive 可以只使用数据文件列表并在“本地模式”下运行伪映射器。所以你把苹果比作大象...... -
顺便问一下,您如何存储数据?分区将是将数据集显式拆分为“可管理”块的第一步。然后列格式(例如 ORC 和 Parquet)将减少应用非常有选择性的 WHERE 过滤器的查询所需的 I/O,和/或仅获取几列 (尽管您的查询不是这种情况,因为您获取所有行和所有列,加上 1)
-
@SamsonScharfrichter 这绝对是 MR 工作的开始;
case语句是造成这种情况的原因,而不是select *(这就是为什么我从“小”子查询测试中完全消除了select *的原因)。但这不是问题;我很好奇为什么它不是针对limit 10子集,而是针对整个数据集(请注意,第二个查询有一个嵌套的limit语句)。