10、count(distinct)
说明 : count(distinct) 在数据量比较大的情况下, 效率并不高
思考: 你知道是为什么吗?
因为该操作需要对全局数据进行去重和计数处理
原因如下: 请问1: 执行count操作的时候, hive翻译的MR, reduce数量是否可以有多个? 必然不会有多个, 只能有一个, 因为全局求最终结果 此时如果执行统计的时候, 需要进行去重,那么去重工作是由reduce执行去重操作, 由于reduce只有一个, 所有的数据都在一个reduce中, 此时reduce的压力比较大 希望执行去重工作可能有多个reduce一起来执行操作, 此时可以将SQL优化: 原有: select count(distinct ip) from ip_tab; 优化: select count(ip) from (select ip from ip_tab group by ip) tmp; 请注意: 这样的做法, 虽然会运行两个MR, 但是当数据量足够庞大的时候, 此操作绝对是值得的, 如果数据量比较少, 此操作效率更低
-- count(distinct)优化 -- 没有优化前。48s select count(distinct city_id) from log_text; -- 优化后。1分22秒 set hive.optimize.countdistinct; -- 默认为true,也就是开启 set hive.optimize.countdistinct=true; select count(city_id) from (select city_id from log_text group by city_id) as tmp; 注意: 为什么优化后运行时间反而增加了呢? 因为目前数据量太小,体现不出优势。类似雅迪和兰博基尼的启动速度
11、笛卡尔积
什么是笛卡尔积呢? 在进行join的时候, 两个表乘积之后结果就是笛卡尔积的结果
比如: 一个表有5条, 一个表有3条数据, 笛卡尔积结果就有15条数据 , 笛卡尔积中有大量数据都是无用数据
什么时候会产生笛卡尔积呢?
在多表join的时候, 关联条件缺少或者使用错误的关联条件以及将关联条件放置在where中都会导致笛卡尔积
在实际使用中, 建议:
1- 在join的时候一定要加上on条件。如果没有可关联的字段,可以写 on 1=1 2- 关联条件要放在on语句里面。不要放在where语句中,因为这种写法会产生笛卡尔积 3- (从业务/需求层面)如果在实际开发中真的发现没有可关联的字段/条件,可以和业务方进行沟通,是否要调整需求,或者条数
示例:
-- 笛卡尔积 -- 关联条件放在on语句中,不会产生笛卡尔积 select * from (select * from log_text where city_id=156) as new_a left outer join log_text b on new_a.city_id=b.city_id; -- 关联条件放在where语句中,会产生笛卡尔积 select * from (select * from log_text where city_id=156) as new_a left outer join log_text b where new_a.city_id=b.city_id;
12、动态分区
需求: 请将下面的一个分区表数据, 拷贝到另一个分区表, 保证对应区数据放置到另一个表的对应区下
如何配置呢?
作用: 帮助一次性灌入多个分区的数据 参数: set hive.exec.dynamic.partition.mode=nonstrict; -- 开启非严格模式 默认为 strict(严格模式) set hive.exec.dynamic.partition=true; -- 开启动态分区支持, 默认就是true 可选的参数: set hive.exec.max.dynamic.partitions=1000; -- 在所有执行MR的节点上,最大一共可以创建多少个动态分区。 set hive.exec.max.dynamic.partitions.pernode=100; -- 每个执行MR的节点上,最大可以创建多少个动态分区 set hive.exec.max.created.files=100000; -- 整个MR Job中,最大可以创建多少个HDFS文件
示例:
-- 动态分区 -- 创建分区表 create table score_part_tb( name string, subject string, score int ) partitioned by (year string) row format delimited fields terminated by '\t'; -- load导入数据 load data inpath '/dir/score.txt' into table score_part_tb partition (year="2022"); -- 数据验证 select * from score_part_tb; -- 动态分区参数设置 set hive.exec.dynamic.partition.mode=nonstrict; -- 开启非严格模式 默认为 strict(严格模式) set hive.exec.dynamic.partition=true; -- 开启动态分区支持, 默认就是true -- 创建表 create table score_part_tb_dynamic( name string, subject string, score int ) partitioned by (dynamic_year string) row format delimited fields terminated by '\t'; -- 验证表结构 show create table score_part_tb_dynamic; select * from score_part_tb_dynamic; -- 动态分区插入数据中,注意partition后面小括号中指定的是前面表的分区字段 insert into score_part_tb_dynamic partition (dynamic_year) select * from score_part_tb;