我试图在Hive中设置一些将日期作为动态参数的视图。在我下面的工作中,我已经交换了在Select子句中使用hiveconf变量,所以我们可以看到发生了什么,但原理保持不变
根据this和this,我应该可以在" $ {hiveconf:dateRangeFrom}"在我的Create View语句中,在运行时提供hiveconf:dateRangeFrom变量以获得最大的快乐,但这并没有发生 - 当创建View时,Hive似乎正在使用分配给变量的任何值,并将其硬编码到查看定义,而不是像运行时那样在运行时替换它。
我有一个解决方法,我为sql文件提供一个参数,然后创建所有视图,替换所需的值,但这不是可持续的
所有工作都在下面,所以你可以看到我是如何得出这个结论的。有什么想法吗?
(需要是最终查询的日期)
hive -e "Select ${hiveconf:dateRangeFrom} , unix_timestamp(${hiveconf:dateRangeFrom} , 'yyyy-MM-dd');" --hiveconf dateRangeFrom='2014-01-01'
日期将按照提供的方式返回,并转换为unix时间戳(例如" 2014-01-01" = 1388534400," 2014-09-12" = 41047640)。可以重复运行脚本,并使用参数相应地更改结果。
CREATE VIEW get_date AS
SELECT ${hiveconf:dateRangeFrom}, unix_timestamp(${hiveconf:dateRangeFrom} , 'yyyy-MM-dd');
这将返回错误:
FAILED: ParseException line 2:8 cannot recognize input near '$' '{' 'hivevar' in select clause
大概是因为它试图进行替换,但$ {hivevar:dateRangeFrom}变量此时尚未初始化
根据: Creating Views in Hive with parameter和 http://mail-archives.apache.org/mod_mbox/hive-user/201205.mbox/%3CBAY151-W9BC976D584FD172E7D70BC0160@phx.gbl%3E
然后可以在Hive视图中使用变量,只要在它们周围使用引号:
CREATE VIEW get_date AS
SELECT "${hiveconf:dateRangeFrom}", unix_timestamp("${hiveconf:dateRangeFrom}" , 'yyyy-MM-dd');
这允许创建视图,因此尝试使用参数调用视图:
hive -e "Select * from get_date" --hiveconf dateRangeFrom='2014-01-01'
只返回变量名称:
${hiveconf:dateRangeFrom} NULL
Time taken: 20.614 seconds, Fetched: 1 row(s)
改为使用单引号:
DROP VIEW get_date;
CREATE VIEW get_date AS
SELECT '${hiveconf:dateRangeFrom}', unix_timestamp('${hiveconf:dateRangeFrom} ', 'yyyy-MM-dd');
给出相同的结果,只是变量名。
SET hiveconf:dateRangeFrom="2014-02-01";
使用不带引号的变量重建原始视图
DROP VIEW get_date;
CREATE VIEW get_date AS
SELECT ${hiveconf:dateRangeFrom}, unix_timestamp(${hiveconf:dateRangeFrom} , 'yyyy-MM-dd');
然后调用"从get_date中选择*;"在会话中给出了预期的结果。
从命令行调用时,使用相同的参数值:
hive -e "Select * from get_date;" --hiveconf dateRangeFrom='2014-02-01'
但是,如果我们使用不同的参数调用视图,那么我们仍然会得到原始答案:
hive -e "Select * from get_date;" --hiveconf dateRangeFrom='2014-09-12'
2014-02-01 1391212800
Time taken: 24.773 seconds, Fetched: 1 row(s)
如果我们在新会话中设置变量:
SET hiveconf:dateRangeFrom="2014-06-01";
甚至没有全部设置,我们仍然得到相同的结果
查看扩展视图定义,原因很明显:
hive> describe extended get_date;
OK
_c0 string
_c1 bigint
Detailed Table Information Table(tableName:get_date, dbName:default, owner:
36015to, createTime:1410523149, lastAccessTime:0, retention:0, sd:StorageDescrip
tor(cols:[FieldSchema(name:_c0, type:string, comment:null), FieldSchema(name:_c1
, type:bigint, comment:null)], location:null, inputFormat:org.apache.hadoop.mapr
ed.SequenceFileInputFormat, outputFormat:org.apache.hadoop.hive.ql.io.HiveSequen
ceFileOutputFormat, compressed:false, numBuckets:-1, serdeInfo:SerDeInfo(name:nu
ll, serializationLib:null, parameters:{}), bucketCols:[], sortCols:[], parameter
s:{}, skewedInfo:SkewedInfo(skewedColNames:[], skewedColValues:[], skewedColValu
eLocationMaps:{}), storedAsSubDirectories:false), partitionKeys:[], parameters:{
transient_lastDdlTime=1410523149}, ***viewOriginalText:SELECT "2014-02-01", unix_t
imestamp("2014-02-01" , 'yyyy-MM-dd'), viewExpandedText:SELECT "2014-02-01", un
ix_timestamp("2014-02-01" , 'yyyy-MM-dd')***, tableType:VIRTUAL_VIEW)
Time taken: 0.123 seconds, Fetched: 4 row(s)
变量替换发生在创建视图时,并将该日期硬编码到定义中:
viewOriginalText:SELECT" 2014-02-01",unix_t imestamp(" 2014-02-01",' yyyy-MM-dd'),viewExpandedText:SELECT" 2014-02-01",un ix_timestamp(" 2014-02-01",' yyyy-MM-dd')
Hive显然是在运行时输入变量的当前值,所以我尝试将其关闭并重新创建查询:
hive> set hive.variable.substitute;
hive.variable.substitute=true
hive> set hive.variable.substitute = false;
hive> set hive.variable.substitute;
hive.variable.substitute=false
“创建视图”语句仍然失败并出现相同的错误:
FAILED: ParseException line 2:8 cannot recognize input near '$' '{' 'hiveconf' in select clause
5)解决方法
如果我们创建一个创建视图的sql文件testParam.sql,我们可以解决这个问题:
DROP VIEW get_date;
CREATE VIEW get_date AS
SELECT ${hivevar:dateRangeFrom}, unix_timestamp(${hivevar:dateRangeFrom} , 'yyyy-MM-dd');
SELECT * FROM get_date;
从命令行调用它可以得到预期的结果:
hive -f testParam.sql --hiveconf dateRangeFrom='2014-08-01'
2014-08-01 1406847600
Time taken: 20.763 seconds, Fetched: 1 row(s)
hive -f testParam.sql --hiveconf dateRangeFrom='2014-09-12'
2014-09-12 1410476400
Time taken: 19.74 seconds, Fetched: 1 row(s)
这确实有效,现在也没问题,但对于分布式的多用户环境来说并不理想。查看视图元数据,我们可以看到视图总是被破坏并使用最新参数重建:
transient_lastDdlTime=1410525287}, viewOriginalText:SELECT '2014-09-12', unix_timestamp('2014-09-12' , 'yyyy-MM-dd'), viewExpandedText:SELECT '2014-09-12', unix_timestamp('2014-09-12' , 'yyyy-MM-dd'), tableType:VIRTUAL_VIEW)
那么,如何创建一个可以在运行时提供动态参数而无需不断重建的视图
答案 0 :(得分:0)
您如何定义daterangeFrom?我认为daterange from可以通过current_date函数动态生成,可以根据您的要求添加和减去天数。您可以简单地使用配置单元功能。
答案 1 :(得分:0)
如果这是您正在寻找的,我不会这样做! 如果你从bash脚本传递值,这应该做的工作:
dateRangeFrom=$(date +"%Y-%m-%d")
hive -e "Select '${dateRangeFrom}' , unix_timestamp('${dateRangeFrom}' , 'yyyy-MM-dd');"
如果要在hive脚本中设置值,可以执行类似这样的操作
hive -e "SET hivevar:dateRangeFrom=2017-11-21;USE mydb; Select '${dateRangeFrom}' , unix_timestamp('${dateRangeFrom}' , 'yyyy-MM-dd');"
如果你想在HQL文件中存储相同的配置单元查询并在外部运行它,那么你需要像这样传递它
hive -f /abc/user/script.hql --hivevar dateRangeFrom=2017-11-21