使用shell进行etl数据验证
方法如下:
整理校验的类型,不同的类型配置文件不一样。
1:校验数据增量:需要设置表名,增量字段。
2:非法值校验:设置表名,条件,校验字段,合法值/非法值范围。
3:自定义校验:设置表名,校验名称,自定义sql。
参数解析:
使用特殊字符作为参数的前缀,后缀;便于在脚本中进行检测和替换。
所实现的脚本如下:
配置文件:
dm_monitor_list.conf
record dm_box_office_summary index_date
record dm_channel_index index_date
record dm_comment_emotion_summary
record dm_comment_keyword_summary
record dm_comment_meterial dt
record dm_event_meterial index_date
record dm_event_meterial_comment dt
record dm_event_summary
record dm_index index_date
record dm_main_actor_index index_date
record dm_movie_comment_summary index_date
record dm_movie_wish_rating_summary dt
record dm_voice_meterial dt
record dm_index_date
record dm_comment_keyword_base
record dm_index_base
record dm_event_meterial_base
primary_check dm_box_office_summary select concat(movie_id,":",rating_type,":",count(1)) as row_val from dm_box_office_summary where index_date='_##dt##_' group by movie_id,rating_type having count(1) >1
primary_check dm_channel_index select concat(movie_id,":",count(1)) as row_val from dm_channel_index where datediff('_##dt##_',index_date)=1 group by movie_id having count(1)>1
primary_cyeck dm_box_office_summary select concat(movie_id,":",index_date,":",value) as row_val from dm_box_office_summary where index_date='_##dt##_' and value<=0
primary_check dm_channel_index select concat(movie_id,":",count(1)) as row_val from dm_channel_index where datediff('_##dt##_',index_date)=1 group by movie_id having count(1)>1
primary_check dm_comment_emotion_summary select concat(movie_id,":",mood_type,":",platform_id,":",channel_id,":",index_date,":",count(1)) as row_val from dm_comment_emotion_summary group by movie_id,mood_type,platform_id,channel_id,index_date having count(1)>1
primary_check dm_comment_keyword_summary select concat(movie_id,":",mood_type,":",keyword,":",platform_id,":",channel_id,":",index_date,":",count(1)) as row_val from dm_comment_keyword_summary group by movie_id,mood_type,keyword,platform_id,channel_id,index_date having count(1)>1
primary_check dm_comment_meterial select concat(comment_id,":",count(1)) as row_val from dm_comment_meterial where dt="_##dt##_" group by comment_id having count(1)>1
primary_check dm_event_meterial select concat(material_url,":",count(1)) as row_val from dm_event_meterial where index_date='_##dt##_' and index_type=1 group by material_url having count(1)>1
primary_check dm_event_meterial_comment select concat(comment_id,":",count(1)) as row_val from dm_event_meterial_comment where dt='_##dt##_' group by comment_id having count(1)>1
primary_check dm_event_summary select concat(event_id,":",platform_id,":",channel_id,":",index_date,":",count(1)) as row_val from dm_event_summary group by event_id,platform_id,channel_id,index_date having count(1)>1
脚本文件:monitor.sh
#!/sh/bash
# 分析表数据量状态
# .数据的唯一性
# 电影id唯一
# .指标的正确行
# 增量不能小于 ;全量表小
# .基本状态
## 运算的条数、电影数量、空间
# 日志格式为
## tablename dt check_type value insert_date
## check_type :
### record 记录值;
### movie_num :电影数量 ;
### space :所占空间
### diff: 昨天和今天的电影差异,使用01 代表今天有昨天没有 代表昨天有今天没有
### movie_rep:重复的电影数量
### index-* :代表某个指标增量的为负值 basepath=$(cd `dirname $`;pwd);
cd $basepath source /etc/profile
source ../../etc/env.ini if [[ ! -f "$basepath/monitor_list.conf" ]]; then
echo "check monitor list file not exists. system exit."
exit
fi
#config
#分区
dt=$(date -d "-1 day" "+%Y-%m-%d")
if [[ $# -eq ]]; then
dt=$(date -d "$1" "+%Y-%m-%d")
fi
insert_date=$(date "+%Y-%m-%d")
file_path=$OPERATION_LOG_FILE_PATH
log_name=monitor_data.log
log=${file_path}/${log_name} cat $basepath/monitor_list.conf | while read line
do
check_type=`echo $line | cut -d " " -f `
table_name=`echo $line |cut -d " " -f `
profix=$table_name"\t"$insert_date"\t" if [[ $check_type == 'dw' ]];then
DB=$HIVE_DB_DW
hdfs_path=$HADOOP_DW_DATA_DESC
elif [[ $check_type == 'ods' ]];then
DB=$HIVE_DB_ODS_S
hdfs_path=$HADOOP_ODS_S_DATA_DESC
fi #record
record=$(spark-sql -e "select count(1) from $DB.$table_name where dt = '$dt';")
echo -e $profix"record\t"$record >> $log #movie_num
if [[ $table_name == 'dw_weibo_materials' ]];then
mtime_id="movie_id"
elif [[ $table_name == 'g4_weibo_materiel_post' ]];then
mtime_id='x_movie_id'
else
mtime_id="mtime_id"
fi
if [[ $table_name == 'dw_weibo_user' ]];then
movie_num=$(hive -e "select count(1) from
(select mtime_actor_id from $DB.$table_name where dt = '$dt' and source = 'govwb' group by mtime_actor_id) a")
else
movie_num=$(spark-sql -e "select count(1) from (select $mtime_id from $DB.$table_name where dt = '$dt' group by $mtime_id) a")
fi
echo -e $profix"movie_num\t"$movie_num >> $log #space
if [[ $check_type == 'ods' ]];then
space=$(hadoop fs -du $hdfs_path/$table_name/$dt)
else
space=$(hadoop fs -du $hdfs_path/$table_name/dt=$dt)
fi
echo -e $profix"space\t"$space>> $log #diff
if [[ $table_name != 'dw_weibo_user' ]];then
yesterday=$(date -d "-1 day $dt" "+%Y-%m-%d")
diff=$(spark-sql -e "
select concat_ws('|',collect_set(flag)) from (
select 'gf' as gf, concat_ws('=',flag,cast(count() as string)) as flag from (
select concat(if(y.$mtime_id is null, , ),if(t.$mtime_id is null,,)) as flag
from (select distinct $mtime_id from $DB.$table_name where dt='$dt') t
full outer join (select distinct $mtime_id from $DB.$table_name where dt='$yesterday') y
on t.$mtime_id = y.$mtime_id
) a group by flag
) b group by gf;")
echo -e $profix"diff\t"$diff>> $log
fi
#movie_rep
if [[ $check_type == 'dw' ]];then
movie_rep=$(spark-sql -e "
select concat_ws('|',collect_set(v)) from (
select 'k' as k ,concat_ws('=',id,cast(count() as string)) as v
from $DB.$table_name where dt = '$dt'
group by id
having count()>
)a group by k;")
echo -e $profix"movie_rep\t"$movie_rep>> $log
fi
#index-*
if [[ $table_name == 'dw_comment_statistics' ]];then
up_day=$(spark-sql -e "select concat('<0:',count(1)) from $DB.$table_name
where dt = '$dt' and
(cast(up_day as int) <
or cast(down_day as int) <
or cast(vv_day as int ) <
or cast(cmts_day as int) <
);")
echo -e $profix"index_day\t"$up_day >> $log
fi
done #dm
args_prefix="_##"
args_suffix="##_"
cat $basepath/dm_monitor_list.conf | while read line
do
check_type=`echo $line | cut -d " " -f `
table_name=`echo $line |cut -d " " -f `
echo "表"$table_name
if [[ $check_type == 'record' ]]; then
dt_str=`echo $line |cut -d " " -f `
echo "记录数校验 分区字段"$dt_str
else
custom_sql=`echo $line |cut -d " " -f -`
echo "自定义校验"$check_type
fi profix=$table_name"\t"$insert_date"\t" DB=$HIVE_DB_DW
hdfs_path=$HADOOP_DW_DATA_DESC if [[ $check_type == 'record' ]]; then
record_sql="select count(1) from $DB.$table_name"
if [[ -n $dt_str ]]; then
# if [[ $table_name == 'dm_channel_index' ]]; then
# record_sql=$record_sql" where datediff('$dt',$dt_str)=1;"
# else
# record_sql=$record_sql" where $dt_str = '$dt';"
# fi
record_sql=$record_sql" where $dt_str = '$dt';"
else
record_sql=$record_sql";"
fi echo "执行的语句:"$record_sql
#record
record=$(hive -e "set hive.mapred.mode = nonstrict;$record_sql")
#record=$(spark-sql -e "$record_sql")
echo -e $profix"$check_type\t"$record >> $log
else
#custom_sql
custom_sql=${custom_sql//$args_prefix"dt"$args_suffix/$dt}
echo "执行的语句:"$custom_sql
invalid_records=$(hive -e "set hive.mapred.mode = nonstrict;use $DB;select concat_ws(\" | \",collect_set(row_val)) from ( $custom_sql ) tmp;")
echo $invalid_records
if [[ ! -n $invalid_records || $invalid_records == '' ]]; then
invalid_records=""
fi
echo -e $profix"$check_type\t"$invalid_records >> $log
fi
done
# insert hive
hadoop fs -rm -r $HADOOP_ODS_CONFIG_DATA_DESC/yq_monitor_data_log/dt=$dt if [ -f "${file_path}/$log_name" ]; then
hive -e "
ALTER TABLE $HIVE_DB_MONITOR.yq_monitor_data_log DROP IF EXISTS PARTITION (dt = '$dt');
alter table $HIVE_DB_MONITOR.yq_monitor_data_log add partition (dt = '$dt');
"
fi
cd $file_path
hadoop fs -put $log_name $HADOOP_ODS_CONFIG_DATA_DESC/yq_monitor_data_log/dt=$dt
mv -f $log_name /home/trash
使用shell进行etl数据验证的更多相关文章
- 使用 JsonPath 完成接口自动化测试中参数关联和数据验证(Python语言)
背景: 接口自动化测试实现简单.成本较低.收益较高,越来越受到企业重视 restful风格的api设计大行其道 json成为主流的轻量级数据交换格式 痛点: 接口关联 也称为关联参数.在应用业务接口中 ...
- 在kettle中实现数据验证和检查
在kettle中实现数据验证和检查 在ETL项目,输入数据通常不能保证一致性.在kettle中有一些步骤能够实现数据验证或检查.验证步骤能够在一些计算的基础上验证行货字段:过滤步骤实现数据过滤:jav ...
- 我这么玩Web Api(二):数据验证,全局数据验证与单元测试
目录 一.模型状态 - ModelState 二.数据注解 - Data Annotations 三.自定义数据注解 四.全局数据验证 五.单元测试 一.模型状态 - ModelState 我理解 ...
- MVC 数据验证
MVC 数据验证 前一篇说了MVC数据验证的例子,这次来详细说说各种各样的验证注解.System.ComponentModel.DataAnnotations 一.基础特性 一.Required 必填 ...
- kpvalidate开辟验证组件,通用Java Web请求服务器端数据验证组件
小菜利用工作之余编写了一款Java小插件,主要是用来验证Web请求的数据,是在服务器端进行验证,不是简单的浏览器端验证. 小菜编写的仅仅是一款非常初级的组件而已,但小菜为它写了详细的说明文档. 简单介 ...
- MVC3 数据验证用法之密码验证设计思路
描述:MVC数据验证使用小结 内容:display,Required,stringLength,Remote,compare,RegularExpression 本人最近在公司用mvc做了一个修改密码 ...
- jQuery MiniUI开发系列之:数据验证
在开发应用系统界面时,往往需要进行很多.复杂的数据验证,当填写的数据符合规定,才能提交保存. jQuery MiniUI提供了比较完美的表单数据验证和错误显示的方式. 常见的表单控件,都有一个验证事件 ...
- AngularJS快速入门指南14:数据验证
thead>tr>th, table.reference>tbody>tr>th, table.reference>tfoot>tr>th, table ...
- atitit.数据验证--db数据库数据验证约束
atitit.数据验证--db数据库数据验证约束 1. 为了加强账户数据金额的安全性,需要增加验证字段..1 2. 创建帐户1 3. 更改账户2 4. ---code3 5. --fini4 1. 为 ...
随机推荐
- 在SQL Server 2008上安装ArcSDE 10.1并实现远程连接
先安装SQL Server 2008 R2 X64(SP2),创建数据库实例,安装客户端. 再安装ArcSDE 10.1,ArcGIS Desktop 10.1,一切顺利. 由于Desktop是32位 ...
- MongoDB慢查询性能分析
最近,长期运营后的港台服出现一个问题,web充值很慢,用gm指令查询玩家信息也很慢.最后定位到MongoDB查询也很慢. 刚开始定位的时候,运营SA直接查指定的玩家,并反映很慢,就猜测是索引的问题 ...
- JDBCTM中Statement接口提供的execute、executeQuery和executeUpdate之间的区别
Statement 接口提供了三种执行 SQL 语句的方法:executeQuery.executeUpdate 和 execute.使用哪一个方法由 SQL 语句所产生的内容决定. 方法execut ...
- vb.net
vb.net 教程: https://www.yiibai.com/vb.net/vb.net_overview.html vb.net 教程 https://www.w3cschool.cn/vb_ ...
- 寒假作业pta1
本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个“*”,要求按下列格式打印 ***** *** * ********所谓“沙漏形状”,是指每行输出奇数个符号:各行符号中心对齐:相邻两行符 ...
- Deloyment Descriptor web.xml
Deployment Descriptor部署描述符: - 部署描述符是要部署到Web容器或EJB容器的Web应用程序或EJB应用程序的配置文件. - 部署描述符应包含EJB应用程序中所有企业bean ...
- JDBC-Oracle连接教程
前言 本文通过一个在Eclipse平台中搭建的小项目,在项目中使用一条静态命令来查询Oracle数据库测试用户“scott”下emp表中的几个字段,来学习JDBC连接数据库的方法.看完之后读者可以基本 ...
- C++ Object实体类
*暂未完成,因为无尽BUG滚滚来. 好长时间没写完,一是能力不够,二是我还得给老板写WEB的代码.可是我不会WEB!js和PHP简直就是世界上最好的语言,因为它们能够让人更快地进入极乐世界. 让我写一 ...
- Java高级特性 第15节 解析XML文档(3) - JDOM和DOM4J技术
一.JDOM解析 特征: 1.仅使用具体类,而不使用接口. 2.API大量使用了Collections类. Jdom由6个包构成: Element类表示XML文档的元素 org.jdom: 解析xml ...
- Log4j源码分析
一.slf4j和log4j的关系: 也就是说slf4j仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已.必须搭配具体的log实现方案比 ...