hive :+中不使用分区?

标签 hive partitioning

我正在查询一个大表,该表分区在一个名为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 inFilter Operator predicate: (day) IN ('2016-04-01', '2016-03-01') (type: boolean) Statistics: Num rows: 100000000 Data size: 9999999999
The hive docs只是说:
“查询中要使用的分区由系统根据分区列上的where子句条件自动确定。”

但不要详细说明。我找不到任何与此直接相关的SO帖子。

谢谢!

最佳答案

tl; dr

根据我在Hue中运行的解释计划,我将 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_YEARSMALLINT,而LOAD_MONTHTINYINT,因此对两者的算术计算将SMALLINT用于结果,并且存储的最大值为32,767(对于yyyymm来说,这是不够的,它需要6位数字,即,至少为999,999)。以INT为100时,将使用INT类型进行计算,并允许数字最大为2147483647。

    说明计划:
    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 :+中不使用分区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36896251/

    相关文章:

    mysql - 处理大数据

    hadoop - 如何使用 ORC 存储 Hive 表以进行复杂查询?

    mysql - 在MySQL,MyISAM中,是否可以将带有分区的表更改为多个硬盘驱动器?

    sql - 优化Oracle order by query

    r - 从配置单元执行 R 脚本

    algorithm - 求解划分问题的递归回溯算法

    sql - 在分区上使用 row_number() 或 dendense_rank() 的计算列

    java - Spark 与 Hive : Table or view not found

    sql - 基于范围的窗口框架只能有 1 个排序键

    sql - 如何在重叠期间优化具有多个计数(不同...)的配置单元查询?