Hive的一些事,原理与技巧(持续更新)

Hive Order/Sort/Distribute/Cluster By:

Order By:会在一个reducer中对所有数据进行排序,为了防止数据量过大导致排序缓慢,hive默认处于strict mode(也即hive.mapred.mode=strict),而且查询语句后面必须跟随limit条件,除非将hive.mapred.mode设置为nonstrict(数据量很大时请慎重设置)

Sort By:会在将数据发往reducer之前进行排序,如果列是数值类型则进行数值排序,如果是字符串类型也将进行词序上的排序。这个排序的效果是每个reducer出来的结果是有序的,但全局不一定有序(也即最终结果是分段有序)。

Distribute By:会将同一个列值的数据发往同一个reducer,但不保证一个列值一个reducer,也不保证发往reducer时将数据排序。例如x1,x2,x4,x3,x1这五个列值发往两个reducer,则reducer1会得到x1,x2,x1,reducer2会得到x4,x3,而且每个reducer中的数据也未排序。

Cluster By:这个排序等同于Distribute By 加 Sort By,例如对上述数据使用Cluster By,则reducer1会得到x1,x1,x2,reducer2会得到x3,x4。然而Cluster By只能指定同一字段的分发和排序,但Distribute By和 Sort By的组合则能指定不同的分发和排序的列值。

补充:官方文档中这段话不是很理解,谁能解释下:Note: It may be confusing as to the difference between SORT BY alone of a single column and CLUSTER BY. The difference is that CLUSTER BY partitions by the field and SORT BY if there are multiple reducers partitions randomly in order to distribute data (and load) uniformly across the reducers.

详细参考:Hive LanguageManual

备注:如果SELECT DISTINCT xxx FROM table SORT BY yyy,会报错Invalid table alias or column reference 'xxx': (possible column names are: _col0),因为使用DISTINCT关键字后会对DISTINCT用到的关键字进行默认的升序排序(可以用ORDER BY或者SORT BY来改变规则),而且使用DISTINCT时,排序的字段必须跟在SELECT中。


Hive 型转换:

Hive支持类型隐式转换,例如会在必要的时候对类型进行隐式转换,例如event_day为string类型,然而碰到where event_day=20140703语句时,int型的20140703会被转换为string类型。

或者使用强制类型转换,例如cast(event_day as double)=20140703.0

详细移步官方文档:Allowed Implicit Conversions、或者Hive数据类型转换


对于Hive的表结构/分区的理解:

首先描述一个现象:

CREATE EXTERNAL TABLE IF NOT EXISTS test (
    name          STRING,
    age           INT
)
PARTITIONED BY (date INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
ALTER TABLE test ADD PARTITION(date=20140710) LOCATION '/test/20140710/';
LOAD DATA LOCAL INPATH "/home/work/20140710.txt" INTO TABLE test PARTITION(date=20140710);
#20140710.txt内容:
#Baron    999999999(注:超出int范围)

A:如上,此时“SELECT * FROM test;”得到的内容中age字段值为NULL;在“ALTER TABLE test CHANGE COLUMN age age STRING AFTER name;”之后重新查询还是之前的效果;但是在“ALTER TABLE test DROP IF EXISTS PARTITION(date=20140710);”并重新添加PARTITION之后,可以查询到age值。

B:反过来,定义表时如果age为STRING型,查询可得到age值,将age字段类型改为int型则查询不到,再改为STRING型之后,可以重新查到数据(这个过程中没有设计PARTITION更新操作)。

在诸多周转测试之后,了解到这么一个现象(或者原理):Hive的PARTITION只受在其之前定义的表结构属性的影响,在PARTITION被创建之后发生的表属性更新,将不影响PARTITION在创建之初所保存的元数据,该元数据保存着先前定义的表的一些属性。

因此,A的PARTITION中元数据保存的字段是INT类型,即使表字段更新为STRING,还是不会更新PARTITION中早已存在的属性。B中PARTITION元数据保存的是STRING类型,改为INT后查不到值(无法转型),再改为STRING类型之后还是能查到,分区中元数据不变。(这段话有点站不住脚跟,不知是不是PARTITION元数据跟HIVE当前表结构共同作用在查询上,产生了交集约束;有朋友对这方面能解释的吗?)



如果文章对你有用,请在收藏之余“顶/赞”一下以示鼓励吧 (/ω\)


你可能感兴趣的:(排序,hive,技巧,转型)