目次
0まえがき
Hiveは、データウェアハウスとデータアナリストに必要なツールの1つです。実際の作業では、ハイブを使用する場合、SQLコードがシェルスクリプトにカプセル化されて実行されることがよくあります。これは、スケジューリングツールによってシェルスクリプトのスケジューリングを容易にする一般的な方法です。
1つのテンプレートコード
#!/bin/bash
lastday=`date --date '-1days' +%Y-%m-%d` #获得昨天的日期
if [ "$2" != "" ];then
lastday=$2
fi;
input_para="hive" #默认启动方式
if [ "$1" != "" ];then
input_para=$1
fi;
#UDF函数使用形式
sqlFun1="CREATE TEMPORARY FUNCTION avgCalShock AS 'jttl.jxresearch.com.hive.udf.avgCalShock' using jar 'hdfs:///phm/JTTL_ETL_COMMON/jx-yjy-udfs-1.0-SNAPSHOT.jar'";
sqlFun2="CREATE TEMPORARY FUNCTION maxCalShock AS 'jttl.jxresearch.com.hive.udf.maxCalShock' using jar 'hdfs:///phm/JTTL_ETL_COMMON/jx-yjy-udfs-1.0-SNAPSHOT.jar'";
sqlFun3="CREATE TEMPORARY FUNCTION minCalShock AS 'jttl.jxresearch.com.hive.udf.minCalShock' using jar 'hdfs:///phm/JTTL_ETL_COMMON/jx-yjy-udfs-1.0-SNAPSHOT.jar'";
input_table="phmdwdb.dwd_iot_phm_switch_shock"; #输入表名
output_table="phmdwdb.dwd_phm_switch_shock_event"; #输出表名
log_dir=${output_table:8};
#Hive的连接方式参数获取(本方案采用oozie传参,也可以将参数放到hdfs上然后获取)
option=`echo ${input_para} | awk -F '_' '{print $1}' | sed s/[[:space:]]//g`
#SQL需要的参数获取
guoche_top_num=`echo ${input_para} | awk -F '_' '{print $3}' | sed s/[[:space:]]//g`
hive_home='/usr/idp/current/hive-client/bin';
sql="
insert overwrite TABLE $output_table
PARTITION (compute_day='$lastday') --注意sql中需要引用shell变量且为字符串时候,此处必须为单引号,使用双引号结果会显示不正确
select
XXX
,XXX
,XXX
from ${input_table}
where from_unixtime(cast(substr(msg_time,1,10) as bigint),'yyyy-MM-dd')='$lastday'
;
";
if [ "$option" = "beeline" ];then
# hive2地址获取
hive_addr=`hadoop fs -cat /phm/JTTL_ETL_COMMON/jdbc.properties | grep hive_addr | awk -F '=' '{print $2}' | sed s/[[:space:]]//g`
hive_url="${hive_addr}/phmdwdb"
cd $hive_home
beeline -u $hive_url -e "$sqlFun1;$sqlFun2;$sqlFun3;$sql" >>/tmp/$log_dir.log 2>&1 ;
fi
if [ "$option" = "hive" ];then
hive -e "$sqlFun1;$sqlFun2;$sqlFun3;$sql" >>/tmp/$log_dir.log 2>&1 ;
fi
#注意使用hive -e "$sql" 而不是hive -e $sql,$sql前必须有双引号。另外日志文件名必须和>>及$sql在同一行。
2コード分析と注意事項
(1)ハイブ-eウェイ
hive -e " 待执行sql
"。このメソッドを使用すると、引用符で実行する必要のあるSQLステートメントを記述できます。通常、長い文章に適しています。この方法は、タスクのスケジューリングが必要な場合に使用される最も直接的な方法でもあります。この場合、変数パラメーター(日付など)をシェルと組み合わせて定義し、スクリプトの自動化をスケジューリングシステムと組み合わせて実現できます。
hive -eで縦線の分割(特殊記号)が発生した場合は、複数のエスケープ文字を追加します
まず、インタラクティブなコマンドラインメソッドを見てみましょう。
各ユーザーの都市と性別を取り出してsplit
関数を使用するとします。次の表現を使用できます。
select
split(location_city, '|')[0] as city,
split(location_city, '|')[1] as gender
from test_0102;
結果を下図に示します。
明らかに、結果は私たちが望むものではありません。これは、垂直線が特別であるためです。エスケープ文字を追加して見てみましょう。
select
split(location_city, '\|')[0] as city,
split(location_city, '\|')[1] as gender
from test_0102;
結果は次のとおりです。
結果は変わらず、期待に応えられませんでした。エスケープ文字を追加した場合。
select
split(location_city, '\\|')[0] as city,
split(location_city, '\\|')[1] as gender
from test_0102;
結果は次のとおりです。
実験を要約すると、最終結果は2つの//を追加することで必要な結果であることがわかります。これは、最初のエスケープ文字がハイブ-> MapReduceプロセスからのエスケープであり、2番目のエスケープ文字がMapReduceコンパイル中のエスケープであるためです。
hive-eの実装を見てみましょう。2つのエスケープ文字を直接使用する場合でも、出力は単語を区切ります。
これは、シェルからハイブに逃げる余分なステップがあるためです。したがって、追加のエスケープ文字が必要です。実際、4つのエスケープ文字が使用されている場合でも、結果は正しいです。特定の法律は直接与えられます:
令需要转义符的个数为 y
如何目标字符串包含'\',则 y = 2^n
如何目标字符串不包含'\',则 y = n
n:跨框架调用的次数,最终算到 java编译为止,一般最常见的就是上面两种情况。
参照リンク:https://blog.csdn.net/lt793843439/article/details/91492088
同様に、二重の垂直線に遭遇した場合は、各垂直線を個別にエスケープする必要があります。たとえば、上記のデータのskills
1つの列を分割するとします。対応する文章は次のとおりです
-
ハイブコマンドライン:垂直バーごとに2つのエスケープ文字
-
hive -e:垂直バーごとに3つのエスケープ文字(4つでもOK)
(2)hive -eが結果ファイルを生成する場合、ファイル名とリダイレクト文字を1行に配置する必要があります
hive -eがhiveSQLを実行するとき、リダイレクト文字(>
)を使用してクエリ結果をファイルに書き込むことができます。
hive -e"
use dac_twelve_dev;
select
split(location_city, '\\\|')[0] as city,
split(location_city, '\\\|')[1] as gender
from test_0102;" > test_0102.txt
cat test_0102.txt
北京 男
上海 女
北京 男
广州 女
西安 男
終了二重引用符、リダイレクト記号、および結果ファイル名は同じ行に配置する必要があることに注意してください。そうしないと、結果ファイルがスケジュールどおりに生成されない場合があります。以下のようになります。
#第一种
hive -e"
your SQL
" >
test_0102.txt
#第二种
hive -e"
your SQL"
>
test_0102.txt
#第三种
hive -e"
your SQL"
> test_0102.txt
上記の3つの方法、最初の方法は次のとおり-bash: syntax error near unexpected token `newline
です。2番目のタイプは画面に結果を印刷した後に同じエラーを報告し、3番目のタイプはエラーなしで結果を画面に印刷しますが、最終的な結果ファイルにはデータがありません。
(3)シェルでSQLを出力するためにhiveSQLを実行するときは、アスタリスクに注意してください。
スケジューリングでhiveSQLを実行する場合、通常はシェルスクリプトファイルが使用されます。スクリプトでは、最初に時間変数を定義し、次にSQLステートメントを定義し、最後にhive-eを使用してSQLを実行します。次のようになります。
yesterday=`date -d "now -1 day" +%Y-%m-%d`
hql="
select * from xxt_able where ds='${yesterday}'
"
echo $hql#错误的写法,正确的是echo "$hql"
hive -e $hql > result.txt
ここhql
で、定義されたステートメントに*
記号(特殊記号など)がある場合、エコーが出力されたときに正常に出力できるようにするために、時間変数が正しく置き換えられているかどうかを確認できることに注意してください。使用する必要があります"$hql"
が$hql
、使用しないでください。それ以外の場合、印刷時に*
番号がシェルワイルドカードとして使用され、現在のパスの下にあるすべてのファイル名が印刷されます。また、ハイブは実行時にエラーを報告します。次のコードと結果に示すように。*
印刷時に、現在のパスにあるすべてのファイルに置き換えられます。
(4)ハイブ実行時のその他のオプションについて
-
-S
mapreduceログをシールドするオプション
hiveSQLを実行するときに、MapReduceプロセスを実行する必要がある場合は、map=100%,reduce=33%
これと同様のプロンプトが画面に表示されます。タスクがより複雑な場合は、それに応じてログの長さが長くなります。タスクの進行状況を理解するのに役立ちますが、ブロックしたい場合もあります。この目標を達成するためにハイブsql语句
をSilent mode
実行するには、hive -S -e " "を使用します。現時点では、画面にはハイブの起動のログのみが表示され、mapreduceプロセスのログは表示されません。
-
-v
このオプションは、実際に実行されたSQLを出力します(SQLのデバッグに使用されます。通常、sh -v +スクリプト名はシェルスクリプトレイヤーでのデバッグに使用されます)
このオプションは、前述のタスクをスケジュールするときに実際に実行された詳細なSQLを検証するために使用できます。昨日の変数を事前に定義していると仮定すると、-v
オプションは変数値を出力し、echo "$hql"
メソッドを置き換えます。(SQLエラーがここに報告されます。変数を示すために、テーブルに存在しないds
フィールドを引用しました)
(5)SQLスクリプトでシェル内の変数を引用する場合は一重引用符が必要であり、文字列です。
1)シェルでの一重引用符と二重引用符の違い
- スクリプトの編集
#!/bin/bash
do_date=$1
echo '$do_date'
echo "$do_date"
echo "'$do_date'"
echo '"$do_date"'
echo ""$do_date""
echo ''$do_date''
echo `date`
- テストスクリプト、結果は次のとおりです
[root@bigdata-1 dan_test]# ./test3.sh '2021-01-04'
$do_date
2021-01-04
'2021-01-04'
"$do_date"
2021-01-04
2021-01-04
2021年 01月 04日 星期一 20:39:41 CST
- 総括する:
- 二重引用符:$変数の値を取ります。
- 一重引用符:そのまま出力、中身を出力、変数値をとらない
(1)一重引用符は、変数値をそのまま使用せずに出力します。
(2)二重引用符は変数値を取ります。
(3)一重引用符は二重引用符の中に入れ子にされ、変数値が取り出されます。変数値が取り出されると、一重引用符は文字列として表示されます。
(4)二重引用符は一重引用符内にネストされ、変数値は取り出されず、二重引用符で囲まれた内容全体が文字列として出力されます。
(5)二重引用符は二重引用符の中に入れ子にされ、変数値は取り出されますが、二重引用符は表示されず、出力全体は文字列として使用されません。二重引用符はオフセットされます。 、これは$ {variable}と同等です。
(6)一重引用符は一重引用符内にネストされ、変数値は取り出されますが、一重引用符は表示されません。出力全体は文字列として使用されず、一重引用符はオフセットされます。 $ {variable}と同等です。
(7)逆引用符 `、コマンドを引用符で囲んで実行します
整体总结:双引号与单引号交替出现,看外层,如果外层是双引号则具备双引号取变量值的功能,且显示单引号。如果外层是单引号则原样输出。
双引号或单引号成对出现:此时无论单引号还是双引号将会被抵消掉,相当于${变量值}
双引号单引号交替出现,但双引号或单引号成偶数出现时,此时主要看外层,外层是双引号则抵消双引号,$里面的值会被解析,此时显示抵消掉双引号后的内容(不常用)
如果外层是单引号,则抵消的是单引号,$里面的值会被解析,此时显示抵消掉单引号后的内容(不常用)
#!/bin/bash
a=110
sql11=" " " '$a' " " "
echo $sql11
〜
#!/bin/bash
a=110
sql11=' " " " '$a' " " " '
echo $sql11
#!/bin/bash
a=110
sql11=' " " "$a" " " '
echo $sql11
#!/bin/bash
a=110
sql11=" ' " " "$a" " " ' "
echo $sql11
外層の交互ではないが連続的な外観の場合、ペアの外観の場合と同じです。
#!/bin/bash
a=110
sql11=' ' """"$a"""" ' '
echo $sql11
#!/bin/bash
a=110
sql11=' " '$a' " '
echo $sql11
#!/bin/bash
a=110
sql11=" ' "$a" ' "(会被用到)
echo $sql11
次のスクリプト:
2)SQLスクリプトでは、文字列形式で「-」を使用して時間を出力する必要があることがよくあります。この場合、二重引用符ではなく一重引用符が必要です。
日でフィルタリングする必要がある場合は、引用符を追加する必要があります。そうしないと、認識されません。時間を出力するときは、引用符を追加する必要があります。そうしないと、文字化けした文字が出力されます。