Hive分区和分桶的通俗解释(附实操例子)

80 阅读5分钟

很高兴你能来阅读,过去一年多,我主要从事天猫国际商品以及订单相关数仓开发与数据分析工作。接下来会陆续分享这段经历中的实战问题、对应解决思路,以及数仓基础的进阶学习总结,希望能给有需要的朋友带来参考和帮助~

一、分区:给数据按“业务维度建文件夹”(解决“翻全量文件”的问题)

image.png

1. 核心逻辑

分区是按业务含义给数据打“文件夹标签” ,把海量数据拆到不同“文件夹”里,查询时只翻目标文件夹,不用扫全部数据。

  • 比喻:你手里有100万条供应商订单数据,若全堆在一个文件夹里,要查“2025年3月供应商A的订单”,得翻完100万条;但你按「月份+供应商ID」建文件夹(比如「dt=202503/supplier_id=10086」),查的时候直接打开这个文件夹,只看里面的几千条数据就行。
  • 技术本质:Hive的分区字段(比如dt、supplier_id)不是数据本身的物理字段,而是“文件夹路径的标签”;底层HDFS里会生成对应路径:/user/hive/warehouse/供应商订单表/dt=202503/supplier_id=10086/,该分区的所有数据文件都存在这个路径下。

2. 你的工作场景实操例子

  • 建表时定义分区:

    •   CREATE TABLE supplier_order (
            order_id string,  -- 订单ID
            amount double,    -- 订单金额
            create_time string -- 下单时间
        ) 
        PARTITIONED BY (dt string, supplier_id string); -- 按“日期(dt)”和“供应商ID”分区
      
  • 加载数据到指定分区:把2025年3月15日、供应商10086的订单数据,放到dt=20250315/supplier_id=10086分区:

    •   LOAD DATA INPATH '/tmp/20250315_10086_order.csv' INTO TABLE supplier_order PARTITION (dt='20250315', supplier_id='10086');
      
  • 查询时指定分区:只查这个分区的数据,速度比扫全表快10倍以上:

    •   SELECT sum(amount) FROM supplier_order WHERE dt='20250315' AND supplier_id='10086';
      

3. 分区的核心特点

  • 分区字段是“人为加的分类标签”,不是数据本身的字段(比如dt可以和create_time一致,但不是同一个东西);
  • 适合按「时间、地区、供应商ID」等“粗粒度维度”拆分,比如按天/月分区、按供应商大类分区;
  • 分区可手动增删,比如删除某一天的分区,直接删对应的文件夹即可。

二、分桶:把“单个文件夹里的文件切小份”(解决“单个文件夹仍太大”的问题)

1. 核心逻辑

分桶是把一个分区内的数据,按“某个字段的哈希值”切成固定数量的小文件(桶) ,查询时直接定位到对应桶,不用扫整个分区的文件。

  • 比喻:你按“20250315”建了一个分区文件夹,里面还是有10G的订单数据,翻起来仍慢;你按“供应商ID”把这10G切成10个小文件(10个桶),每个桶存1G数据(比如ID尾号0的在桶0,尾号1的在桶1…),查供应商10086(尾号6)时,直接打开桶6的文件就行,不用扫10G。
  • 技术本质:分桶字段(比如supplier_id)是数据本身的物理字段;Hive会对分桶字段做哈希计算,把数据均匀分到指定数量的桶文件里,每个桶对应一个文件。

2. 工作场景案例

  • 建表时定义分桶(先分区,再在分区内分桶):

    •   CREATE TABLE supplier_order (
            order_id string,
            amount double,
            create_time string,
            supplier_id string -- 分桶字段(数据本身的字段)
        ) 
        PARTITIONED BY (dt string) -- 先按日期分区
        CLUSTERED BY (supplier_id) INTO 10 BUCKETS; -- 每个分区内按供应商ID分10
  • 加载数据后:dt=20250315这个分区里,会生成10个桶文件(0_0、1_0…9_0),每个桶里存一批供应商ID的订单数据;

  • 查询时:指定分区+分桶字段,Hive直接定位到对应桶,速度再提一个量级:

    •   SELECT sum(amount) FROM supplier_order WHERE dt='20250315' AND supplier_id='10086';
      

3. 分桶的核心特点

  • 分桶字段是数据本身的字段,不是标签;
  • 适合按「高频查询的细粒度维度」拆分,比如供应商ID、订单ID;
  • 分桶数固定(建表时定),数据分布更均匀,还能支持高效的抽样查询(比如随机查10%的供应商数据)。

三、分区vs分桶 核心区别(一张表看懂)

维度分区分桶
本质按“业务标签”建文件夹(逻辑拆分)按“哈希值”切文件(物理拆分)
字段属性非数据本身的标签字段数据本身的物理字段
拆分粒度粗粒度(时间、地区、供应商大类)细粒度(供应商ID、订单ID)
数量灵活性可随时增删分区(比如加新月份)建表时固定分桶数,不能改
核心作用减少扫描的“文件夹范围”减少扫描的“文件范围”

四、实际工作中怎么用

比如分析供应商订单时,先按「日期(dt)」分区(解决“查全年数据慢”),每个日期分区内再按「供应商ID」分10桶(解决“单日期内数据仍多”),查询效率能比不分区分桶提升几十倍。