返回顶部

我的蜡笔丢了

  博客园  :: 首页  :: 新随笔  ::  :: 订阅 订阅  :: 管理

原文连接:https://cwiki.apache.org/confluence/display/Hive/ListBucketing

  • 场景分析
    • 假设我们创建的分区表的结构如:create table T(a, b, c, ....., x) partitioned by (ds);
    • 但是需要高效地执行查询:select ... from T where x = 10; (没有用到分区而是用到其中一个列,x列是存在数据倾斜的列)这样查询的话,会出现数据倾斜现象,x列中大概有10个值具有非常大的倾斜,其余的值是比较小的数,运行的时候,任务会出现倾斜现象
  • 解决方案
    • 方案一:将x列添加到分区中 create table T(a,b,c, .......) partitioned by (ds, x);
    • 优缺点
      • 优点:分区的添加让数据定位更加快捷
      • 缺点:新增一个字段作为分区字段,让分区更加详细了,但是HDFS的文件数量增加;HDFS中的中间文件数量增加;Metastore元数据表将随着分区的数量增加而增加,带来一定的压力
    • 方案二:倾斜表(List Bucketing)
  • 定义
    • 倾斜表可以识别具有倾斜严重的key,每个倾斜严重的key都有一个单独的目录,其余的键都进入另外一个others的目录
    • 此映射在元存储中的表或分区级别里维护,并由配置单元编译器用于执行输入修剪
    • 倾斜键的列表存储在表级别(该列表最初可以由客户机定期提供,最终可以在加载新分区时更新)
  • 例子说明
    • 一个表维护了“x”的倾斜key列表:6, 20, 30, 40,当加载一个新分区时,它将创建5个目录(4个倾斜key目录+1个所有剩余键的默认目录),加载的表/分区将具有以下映射:6、20、30、40、others
    • 这与当前的hash bucketing类似,bucket编号决定文件编号。因为倾斜键不需要是连续的,所以倾斜键的整个列表需要存储在每个表/分区中。
    • 当执行 select ... from T where ds = '2012-04-15' and x = 30; Hive编译器会使用对应x=30的目录执行map reduce作业
    • 当执行 select ... from T where ds = '2012-04-15' and x = 50;Hive编译器会使用对应x=others的目录执行map reduce作业
  • 使用场景
    • 每个分区的倾斜键占总数据的很大一部分。在上面的示例中,如果倾斜键(6、20、30和40)只占用数据的一小部分(比如20%),那么x=50形式的查询仍然需要扫描剩余的数据(80%)
    • 每个分区的倾斜键的数量非常少。数量过大,会给元数据存储带来压力
  • 扩展优化:以扩展到多个key组合的情况
  • 假设我们要优化的查询 select ... from T where x = 10 and y = 'b'; 对于组合键(x,y)的每个倾斜值,会存储文件偏移量。因此,元存储将具有如下映射:(10,'a')->1,(10,'b')->2,(20,'c')->3,(others)->4
    • 如果多个key都同时使用到的话,那么可以会快定位到文件目录所在,但是如果只是使用某个key的话,例如 select ... from T where x = 10; 或者 select ... from T where y = 'b'; 这样的话,只能过滤掉一些不符合条件的目录(是否是组合键的前缀没有影响,可能内部会有优化?)
    • 当x=10的条件下,编译器可以减少对(20,'c')文件目录的扫描
    • 对于y='b',可以减少对(10,'a')和(20,'c')的文件目录的扫描,但是对于其他(others)是没有帮助的
    • 如果在查询中,没有指定对应的倾斜key,那么就是扫描所有的数据进行过滤
  • Skewed Table vs. List Bucketing Table
    • Skewed Table是具有倾斜信息的表(普通的表,但是数据会倾斜)
    • List Bucketing Table是一个倾斜表,它会为倾斜值创建子目录
  • 操作验证
    • 由于倾斜表的子目录性质,所以不能和某些特性共存
    • DDL:list bucketing table和以下共存会编译报错
      • 正常的分桶表 (clustered by, tablesample, etc.)
      • 外部表
      • 使用“load data …”加载数据
      • 使用 CTAS (Create Table As Select) 语句
    • DML:list bucketing table和以下共存会编译报错
      • 使用“insert into”插入数据
      • 正常的分桶表(clustered by, tablesample, etc.)
      • 外部表(external table)
      • non-RCfile due to merge
      • non-partitioned table
      • 分区值不应与默认的列表list bucketing table目录名相同
    • 修改表连接(Alter Table Concatenate):list bucketing table和以下共存会编译报错
      • non-RCfile
      • external table for alter table
  • 操作:
    • 创建表 Create Table
    • 创建一个倾斜表,为所有分区创建倾斜信息  CREATE TABLE <T> (SCHEMA) SKEWED BY (keys) ON ('c1', 'c2') [STORED AS DIRECTORIES];
    • 例如:
      • create table T (c1 string, c2 string) skewed by (c1) on ('x1') stored as directories;
      • create table T (c1 string, c2 string, c3 string) skewed by (c1, c2) on (('x1', 'x2'), ('y1', 'y2')) stored as directories;
      • 注:“STORED AS DIRECTORIES”是可选参数。它告诉Hive它不仅是一个倾斜表,而且是个list bucketing表:为倾斜的值创建子目录  
    • 修改表 Alter Table
    • 修改普通表表为倾斜表(只支持表级别,不支持分区表)ALTER TABLE <T> (SCHEMA) SKEWED BY (keys) ON ('c1', 'c2') [STORED AS DIRECTORIES];
      • 将表从非倾斜表转换为倾斜表
      • 更改倾斜表的列名或倾斜值
    • 表转换:将倾斜表转换为普通表 ALTER TABLE <T> (SCHEMA) NOT SKEWED;
      • 关掉表的倾斜功能,使得表为普通表非倾斜表
      • 关闭"list bucketing" 的功能
    • 修改倾斜表不额外创建分区目录  ALTER TABLE <T> (SCHEMA) NOT STORED AS DIRECTORIES;
      • 关闭"list bucketing" 的功能
      • not turn off the "skewed" feature from table since a "skewed" table can be a normal "skewed" table without list bucketing.
    • 更改倾斜表的倾斜key的location位置  ALTER TABLE <T> (SCHEMA) SET SKEWED LOCATION (key1="loc1", key2="loc2");
  • 设计
    • 在加载这样的表时,最好为每个倾斜键创建一个子目录。可以使用类似于动态分区的基础结构。
    • Alter table<T>partition<P>concatenate;
    • 需要更改以合并每个目录的文件。
posted on 2021-03-10 09:56  我的蜡笔丢了  阅读(1266)  评论(0)    收藏  举报