hive中有一个优化是, 默认hive处理数据按行处理,开启后会按批处理,加快我们的执行效率. 官方文档: https://cwiki.apache.org/confluence/display/Hive/Vectorized+Query+Execution 开启参数如下:
SET hive.vectorized.execution.enabled = true;
# 关键优化参数,一般是指的map端开启的矢量化SET hive.vectorized.execution.reduce.enabled = true;
# 注意这个优化一般是计算引擎为tez 或者 spark的时候才会生效
# 插入测试数据
drop table if exists user_sessions;
CREATE TABLE user_sessions (
user_id INT,
login_ts TIMESTAMP, -- 登录时间
logout_ts TIMESTAMP -- 登出时间
) STORED AS orc;
INSERT INTO TABLE user_sessions VALUES
(101, '2023-09-21 08:00:00', '2023-09-21 08:30:00'),
(102, '2023-09-21 09:00:00', '2023-09-21 09:30:00'),
(103, '2023-09-21 09:10:00', '2023-09-21 10:30:00');
# 需求: 查询用户的的在线时间,并按照在线时间排序?
# 开启矢量化优化
SET hive.vectorized.execution.enabled = true;
# 可以通过下面的查询执行计划, 发现已开启矢量化
explain VECTORIZATION select
user_id,
unix_timestamp(logout_ts),
unix_timestamp(login_ts),
unix_timestamp(logout_ts) - unix_timestamp(login_ts) sjc
from user_sessions
order by login_ts, logout_ts;
# 执行查询
select
user_id,
unix_timestamp(logout_ts),
unix_timestamp(login_ts),
unix_timestamp(logout_ts) - unix_timestamp(login_ts) sjc
from user_sessions
order by login_ts, logout_ts;
上面的查询结果正常, 没有任何问题. 注意解解下来我们对上面的计算做一个处理
cast((unix_timestamp(logout_ts) - unix_timestamp(login_ts)) as int) sjc
# 调整后查询, 注意这个仍然是在开启矢量化下面进行
select
user_id,
unix_timestamp(logout_ts),
unix_timestamp(login_ts),
cast((unix_timestamp(logout_ts) - unix_timestamp(login_ts)) as int) sjc
from user_sessions
order by login_ts,logout_ts;
经过上面的查询, 你会惊奇的发现 sjc 计算结果全部为0. 而我们查询仅仅是对类型做了一个cast转换, unix_timestamp是一个bigint类型 相当于做了一个bigint->int的转换,这个是一个向下转换,转换过程本身可能出现数据丢失.
# 在上面的基础上
# 关闭矢量化优化
SET hive.vectorized.execution.enabled = false;
select
user_id,
unix_timestamp(logout_ts),
unix_timestamp(login_ts),
cast((unix_timestamp(logout_ts) - unix_timestamp(login_ts)) as int) sjc
from user_sessions
order by login_ts,logout_ts;
当我们关闭矢量化计算的时候, 你会发现,计算结果一切正常, 可以正确的计算出结果, 下面我们进一步测试
# 开启矢量化
SET hive.vectorized.execution.enabled = true;
select
user_id,
unix_timestamp(logout_ts),
unix_timestamp(login_ts),
cast(current_timestamp() as int), -- 对常量数据做转换
cast(unix_timestamp(login_ts) as int), -- 对矢量化数据做转换
cast((unix_timestamp(logout_ts) - unix_timestamp(login_ts)) as int) sjc
from user_sessions
order by login_ts,logout_ts;
上面的计算,你会发现, 开启矢量化的情况下面, 对常量数据做转换是可以正常的. 涉及到对矢量化的数据计算就差出现错误 根据上面的测试, 推测,cast 在矢量化计算上面,可能存在bug [hive2 hive3都做过测试] 所以请大家在矢量化计算过程, 使用cast的时候注意下,尤其是向下转换的时候.
1