赞
踩
转载请注明出处:https://blog.csdn.net/l1028386804/article/details/88430330
按天划分的表
按天划分就是一种模式,通常会在表名中加入时间,例如:supply_2019_03_10、supply_2019_03_11等。
- hive> create table supply_2019_03_10 (id int, part string, quantity int);
- hive> create table supply_2019_03_11 (id int, part string, quantity int);
- hive> create table supply_2019_03_12 (id int, part string, quantity int);
- hive> ....load data....
- hive> select part, quantity from supply_2019_03_10
- > union all
- > select part, quantity from supply_2019_03_11
- > where quantity < 4;
对于Hive,这种情况下,可以使用分区表。Hive通过where子句中的表达式来选择查询所需要的指定的分区。
- hive> create table supply(id int, part string, quantity int) partitioned by (day int);
- hive> alter table supply add partition (day=20190310);
- hive> alter table supply add partition (day=20190311);
- hive> alter table supply add partition (day=20190312);
- hive> .... load data ....
- hive> select part, quantity, from supply where day >= 20190310 and day < 20190311 and quantity < 4;
关于分区
一个理想的分区方案不应该导致差生太多的分区和文件夹目录,并且每个目录下的文件应该足够的大,应该是文件系统中块大小的若干倍。
可以按照时间粒度进行分区:
- hive> create table weblogs(url string, time long, state string, city string)
- > partitioned by (day int);
- hive> select * from weblogs where day=20190311;
也可以使用两个级别的分区并且使用不用的纬度。比如:第一个分区按照天(day)分区,二级分区以州名(state)进行划分。
- hive> create table weblogs(url string, time long, city string)
- > partitioned by (day int, state string);
- hive> select * from weblogs where day=20190311;
同一份数据,多种处理
从一个数据源产生多个数据聚合,而无需每次聚合都要重新扫描一次。
比如:下面两个查询都会从源表history表读取数据,然后倒入扫2个不同的表中:
- hive> insert overwrite table sales
- > select * form history where action = 'purchased';
- hive> insert overwrite table credits
- > select * from history where action = 'returned';
上面的查询语法是正确的,就是执行效率低下,下面这个这个查询可以达到同样的目的,只需要扫描history表一次即可:
- hive> from history
- > insert overwrite sales select * where action = 'perchased'
- > insert overwrite create select * where action = 'returned';
对于每个表的分区
有时需要对Job的中间结果的临时表进行分区,以避免任务失败,重新从开始执行任务,或者某天、某些数据被覆盖掉。
例如:下面这个例子中涉及了一个名为distinct_ip_in_logs的中间表,其会在后续处理步骤中使用到:
- hive --hiveconf dy=20190311
- hive> insert overwrite table distinct_ip_in_logs
- > select distinct(ip) as ip from weblogs
- > where hit_date = '${hiveconf:dt}';
-
- hive> create table state_city_for_day(state string, city string);
- hive> insert overwrite state_city_for_day
- > select distinct(state, city) from distinct_ip_in_logs
- > join geodata on (distinct_ip_in_logs.ip = geodata.ip);
这种方式有效,不过当计算某一天的数据时会导致前一天的数据被insert overwrite语句覆盖掉。如果同时运行两个这样的示例,用于处理不同日期的数据的话,那么它们就可能会相互影响到对方的结果数据。
一个更具鲁棒性的处理方法是在整个过程中使用分区。这样就不会存在同步问题。还可以对中间数据按日期进行比较
- hive --hiveconf dt=2019-03-11
- hive> insert overwrite table distinct_ip_in_logs
- > partition(hit_date=${dt})
- > select distinct(ip) as ip from weblogs
- > where hit_date = '${hiveconf:dt}';
-
- hive> create table state_city_for_day (state string, city string) partitioned by (hit_date string);
-
- hive> insert overwrite table state_city_for_day partition(${hiveconf:dt})
- > select distinct(state, city) from distinct_ip_in_logs
- > join geodata on (distinct_ip_in_logs.ip = geodata.ip)
- > where (hit_date = '${hiveconf:dt}');
这种方法的缺点是,需要管理中间表并删除旧分区,不过这些任务也很容易实现自动化处理。
分桶表数据存储
分桶是将数据集分解成更容易管理的若干部分的另一个技术。
如果我们对表weblog进行分桶,并使用user_id字段作为分桶字段,则字段值会根据用户指定的值进行哈希分发到桶中。同一个user_id下的记录通常会存储到同一个桶中。假设用户数比桶数多得多,则每个桶内就将会包含多个用户的记录:
- hive> create table weblog (user_id int, url string, source_ip string)
- > partitioned by (dt string)
- > clustered by (user_id) into 96 buckets;
不过,将数据正确的插入到表的过程完全取决于用户自己!create table语句中所规定的信息仅仅定义了元数据,而不影响实际填充表的命令。
使用insert ... table语句时,需要正确的填充表,首先,需要设置一个属性来强制Hive为目标表的分桶初始化过程设置一个正确的reducer个数。然后我们再执行一个查询来填充分区。例如:
hive> set hive.enforce.bucketing=true;
如果没有设置hive.enforce.bucketing属性,就需要自己设置和分桶个数相匹配的reducer个数,例如:使用set mapred.reduce.tasks=96,然后在insert语句中,需要在select语句后增加cluster by语句。
为表增加列
- hive> create table weblogs(version long, url string)
- > partitioned by (hit_date int)
- > row format delimited fields terminated by '\t';
-
- hive> load data local inpath 'log1.txt' into table weblogs partition(20190101)
- hive> select * from weblogs;
增加一个user_id字段
- hive> alter table weblogs add columns(user_id string);
- hive> load data local inpath 'log2.txt' into table weblogs partition(20190102);
- hive> select * from weblogs;
注意:通过这些方式,无法在已有字段的开始或者中间增加新字段。
使用列存储表
重复数据,像state字段和age字段这样的列将会有很多重复的数据。这种类型的数据如果使用列式存储将会非常好。
多列,表中有很多的列,查询通常只会使用到一个字段或者很少的一组字段,基于列式存储将会使分析表数据执行的更快:
hive> select distinct(state) form weblogs;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。