定义
Hive中有一个虚拟列的概念,类似于Oracle中伪列。在Hive中虚拟列并不真实存在于表中,在0.8.0版本后有以下几种生成虚拟列的方式:
INPUT__FILE__NAME:其值对应的是map task所处理的输入文件名
BLOCK__OFFSET__INSIDE__FILE:For blockCompressed files,表示RCFile Block orSequenceFile 当前块在文件中的偏移量;For non-block-compressedfiles, 表示当前行的偏移量.
ROW__OFFSET__INSIDE__BLOCK:使用该虚拟列特性的时候,需要启用参数hive.exec.rowoffset(默认关闭)。For non-block-compressed files这个值一直为0,否则表示行号.
用途
Hive伪列应该是属于比较冷门的概念。如Wiki上所描述的:It is important to note, that all of the virtual columns listed here cannot be used for any other purpose(没有特殊目的)。但是笔者经过资料查询,其实是有两种场景可以使用到伪列的(笔者在日常工作中是没有使用过的):
1、伪列可用于定位查询某些异常数据所在的文件位置
2、虚拟列可用于生成代理键
3、可以通过虚拟列来统计表所生成的文件个数
接下来就为大家演示一下用来扩展大家的知识面:
使用
异常数据所在位置定位
select
split(reverse(INPUT__FILE__NAME),'/')[0] as file_name,BLOCK__OFFSET__INSIDE__FILE,ROW__OFFSET__INSIDE__BLOCK
from test_table
where sale_price>20
经过上述代码的执行,可得到售卖价格大于20的记录所在的文件位置。结果如下图:
通过类似的方式可以用来定位比如某个列字段值过大无法完全展示或者异常数据所在的文件,然后通过文件查看的方式来定位具体的异常数据。
代理键的生成
在数仓建模中,有代理键的概念。但针对分布式系统来说,其代理键的生成和唯一性的保障相对来说是比较困难的,所以针对于大数据生态系统来说,很少见有代理键生成的逻辑。但通过Hive虚拟列的功能或许可以将代理键的实现成为一种可能。
select
concat(cast(regexp_replace(reverse(split(reverse(INPUT__FILE__NAME),'/')[0]),'_','') as int),BLOCK__OFFSET__INSIDE__FILE,ROW__OFFSET__INSIDE__BLOCK) as row_num
from test_table
limit 10
如上图所示:将每条记录所在的文件、偏移量进行拼接得到对应的id。
select
count(1) as all_cnt,
count(distinct row_num) as unique_cnt
from
(
select
concat(cast(regexp_replace(reverse(split(reverse(INPUT__FILE__NAME),'/')[0]),'_','') as int),BLOCK__OFFSET__INSIDE__FILE,ROW__OFFSET__INSIDE__BLOCK) as row_num
from test_table
)result
上述代码用来校验其生成rowID的唯一性,结果如下:(需要注意的是该逻辑只能保证当前表在append模式下才可以使用,否则文件重生成可能会造成记录对应的rowID发生改变)
统计文件个数
通过使用INPUT__FILE__NAME虚拟列可以帮助我们无需使用shell来统计表所生成的文件个数.
select count(distinct INPUT__FILE__NAME) from test_table