Hive:where + in 不使用分区?
Posted
技术标签:
【中文标题】Hive:where + in 不使用分区?【英文标题】:Hive: where + in does not use partition? 【发布时间】:2016-04-27 16:59:23 【问题描述】:我正在查询一个在名为day
的字段上分区的大表。
如果我运行查询:
select *
from my_table
where day in ('2016-04-01', '2016-03-01')
我得到了许多映射器和缩减器,并且查询需要很长时间才能运行。
但是,如果我写一个查询:
select *
from my_table
where day = '2016-04-01'
or day = '2016-03-01'
我得到的映射器和缩减器要少得多,而且查询运行得很快。 对我来说,这表明in
没有利用表中的分区。谁能证实这一点并解释原因?
Hive 版本:1.2.1 Hadoop 版本:2.3.4.7-4
详情:
我相信执行计划的相关部分是......
使用Where or
根本没有过滤运算符
使用Where in
Filter Operator
predicate: (day) IN ('2016-04-01', '2016-03-01') (type: boolean)
Statistics: Num rows: 100000000 Data size: 9999999999
The hive docs 只是说: '在查询中使用哪些分区由系统根据分区列上的 where 子句条件自动确定。'
但不要详细说明。我找不到任何与此直接相关的 SO 帖子。
谢谢!
【问题讨论】:
和between
操作符一样
Hive 1.2.0 中存在此问题
【参考方案1】:
tl;博士
根据说明,我正在使用 Hive 1.1.0 和 Cloudera 5.13.3 和 IN
遵循与等号运算符 (=
) 相同的优化我在顺化运行的计划。
示例
我的表在LOAD_YEAR (SMALLINT)
和LOAD_MONTH (TINYINT)
上进行了分区,并且有这两个分区:
load_year=2018/load_month=10
(19,828,71 行)
load_year=2018/load_month=11
(702,856 行)
以下是各种查询及其解释计划。
1.等号 (=
) 运算符
查询:
SELECT ID
FROM TBL
WHERE LOAD_MONTH = 11Y
解释计划:
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Fetch Operator
limit: -1
Processor Tree:
TableScan
alias: tbl
filterExpr: (load_month = 11) (type: boolean)
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: id (type: string)
outputColumnNames: _col0
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
ListSink
2。 IN
运营商
查询(注意数据中没有第12个月):
SELECT ID
FROM TBL
WHERE LOAD_MONTH IN (11Y, 12Y)
解释计划:
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Fetch Operator
limit: -1
Processor Tree:
TableScan
alias: tbl
filterExpr: (load_month = 11) (type: boolean)
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: id (type: string)
outputColumnNames: _col0
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
ListSink
3.与 AND 和 OR 结合使用等于 (=
)
查询:
SELECT ID
FROM TBL
WHERE
(LOAD_YEAR = 2018S AND LOAD_MONTH = 11Y)
OR (LOAD_YEAR = 2019S AND LOAD_MONTH = 1Y)
解释计划:
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Fetch Operator
limit: -1
Processor Tree:
TableScan
alias: tbl
filterExpr: (((load_year = 2018) and (load_month = 11)) or ((load_year = 2019) and (load_month = 1))) (type: boolean)
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: id (type: string)
outputColumnNames: _col0
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
ListSink
4.算术运算
查询:
SELECT ID
FROM TBL
WHERE (LOAD_YEAR * 100 + LOAD_MONTH) IN (201811, 201901)
旁注:
100 没有后缀,所以它是一个INT
,而(LOAD_YEAR * 100 + LOAD_MONTH)
也是一个INT
。这确保了结果是准确的。由于LOAD_YEAR
是SMALLINT
和LOAD_MONTH
和TINYINT
,因此对两者的算术计算使用SMALLINT
作为结果,存储的最大值为32,767(对于yyyymm
来说不够,需要6 位数字,即,至少高达 999,999)。将 100 作为 INT
时,使用 INT
类型进行计算,并允许最多 2,147,483,647 的数字。
解释计划:
STAGE DEPENDENCIES:
Stage-0 is a root stage
STAGE PLANS:
Stage: Stage-0
Fetch Operator
limit: -1
Processor Tree:
TableScan
alias: tbl
filterExpr: (201811) IN (201811, 201901) (type: boolean)
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: id (type: string)
outputColumnNames: _col0
Statistics: Num rows: 702856 Data size: 84342720 Basic stats: COMPLETE Column stats: NONE
ListSink
总结
所有这些查询只扫描第二个分区,从而避免了另一个分区中的约 2000 万行。
【讨论】:
以上是关于Hive:where + in 不使用分区?的主要内容,如果未能解决你的问题,请参考以下文章