本文主要包括:
众所周知,制订交通法规表面上是要限制行车权,实际上是保障公众的人身安全。试想如果没有限速,没有红绿灯,没有靠右行驶条款,谁还敢上路。消防局最主要的工作不是灭火,而是为了不发生火灾建立很多规范。如果发生火灾,说明前面的工作没有做到位。
同理,对于数仓开发来说,开发规范不是消灭开发的创造性、优雅性,而是限制过度个性化,推行相对标准化,以一种普遍认可的方式一起做事。
为此,针对数据研发而言,整理以下开发规范:
- 代码开发规范
- 调度系统使用规范
- 任务上线流程
设计开发规范的长远目标是从有到无,因为人人自觉遵守,规范和谐地融入开发整个流程,规范似乎消失了,但又无处不在。
代码开发规范
数据研发分为离线任务和实时任务,两种任务的开发流程完全不同,故开发规范需要分别定制
离线任务
通用规范
离线数仓的开发,主要是开发sql任务(hive sql/impala sql),针对sql任务,制定以下规范:
- 通过编写shell脚本来开发sql任务,一个shell脚本最终只输出一个结果表。中间生成的临时表需要在脚本最后删除
- 任务的调度使用DolphinScheduler,每天定时启动
- 默认情况下,执行引擎使用Hive-MR,除非对实效性要求很高,可以切换到Impala
- 一个hive-cli只能执行一个sql,即一个sql语句不能含有多个
;
- 脚本统一在自己本地开发,后上传到gitlab,通过DolphinScheduler的代码发布项目(projectDeploy)发布到线上
- 如果引用的hive表是分区表,必须指定分区范围,如dt = ‘20220420’
- 禁止使用
select *
- 所有的报表和模型开发必须先出设计再进行开发
注释规范
脚本的开头以及每个sql语句都必须有注视
- 注释内容要清晰明了,含义准确,避免歧义
- 字段注释紧跟在字段后面
- 应对不易理解的分支条件表达式加注释
- 对重要的计算应说明其功能
- 过长的函数实现,应将其语句按实现的功能分段加以概括性说明
- 原则上所有表、字段、任务都需要添加注释,任务有特定的注释规范,见下文任务注释说明
任务注释说明:
# # # # # # -CopyRight# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # -
# AppName: offline_ods_bm_cust_info
# Description: 计算售前商机_客户基本信息表,保留历史与最新的数据
# Source Table:
# pom.stg_bm_cust_info
# Output Table:
# pom.ods_bm_cust_info
# Version 1.00
# Language:bash shell
# CreateDate: 2022/04/14 14:43
# Author: gujc
# ITCode: 17405
# Email: gujc@digiwin.com
# # # # # # Update Log# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# 2022-04-15 修改history分区数据不全的问题
# # # # # # Environment# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
- 提供任务名,方便任务创建时任务的获取以及平台中任务查询
- 提供创建者、创建日期、功能描述等信息,方便后期维护跟踪
- 提供代码变更历史,便于了解代码演进历史及依据
- 提供脚本依赖表清单,方便后续任务依赖配置
- 提供输出表清单,方便确认是否单个目标表
SQL编写规范
- 关键字最好大写,如SELECT、FROM、WHERE等,字段名不做要求
- 字段排列要求
- SELECT 语句选择的字段按每行一个字段方式编排;
- SELECT 单词后面一个空格后直接跟首个选择的字段,其他字段前”,”点后放字段名
- 建议每个SELECT的字段后面都有注释,至少在SQL的最外层的SELECT必须要有,并且多个字段的注释对其在同一列上
SELECT first_name --第一个名字 ,last_name --最后一个名字 ,salary --工资 ,itcode --工号 FROM employee WHERE salary > 35000;
- SELECT子句排列要求
SELECT语句中所用到的FROM、WHERE、GROUP BY、HAVING、JOIN、UNION等子句
- 换行编写
- 与相应的SELECT语句对齐
- WHERE子句下面的逻辑判断符AND、OR等与WHERE左对齐编排
SELECT cust_id ,num FROM cust WHERE num >= 100 AND num <= 200 OR proname = 'ORANGE' ORDER BY num;
- 算术运算符、逻辑运算符前后至少保留一个空格
SELECT SUM(t1.num * t2.price) / 2 AS total_amt FROM fruit_orders t1 INNER JOIN fruit_inventory t2 ON t1.proid = t2.proid WHERE t2.proname = 'ORANGE' AND num <= 200;
- 一个sql语句最多join 3次,大于3次的,先创建临时表,关联临时表,这样可以使逻辑更清晰,并且方便调查数据问题
其他规范可以参考HQL过程体开发规范
任务脚本案例
数仓脚本开发统一提交到DataWarehose
为了方便编码,让数据研发人员专注于业务逻辑,这里对shell异常捕捉、执行引擎的选择等做了封装,开发人员只要按照固定的模版填充sql即可:
- 删除hive临时表:
参数说明:V_MSG=" clear Temporary table ${TABLE_TMP_01},write into Temporary table" drop_tmp_table -tbn "${TABLE_TMP_01}" -engine hive -env hwCloud
-tbn:表名
-engine:选择执行引擎,这里目前可以选择hive和impala
-env: 执行环境
hwCloud:华为云
aliCloud:阿里云正式区
aliCloudTest: 阿里云测试区
azureCloud: 微软云
- 执行sql语句:
参数说明:V_MSG="INSERT OVERWRITE TABLE partition active" V_SQL=" INSERT OVERWRITE TABLE ${TABLE_TMP_01} partition(dp = 'active',end_date = '99991231') SELECT activity_id --活动id ,activity_no --活动编号 ,activity_name --活动名称 ,transaction_times --交易次数 ,contact_times --接触次数 ,manage_status --状态 ,tenantsid --租户id FROM ${TABLE_INPUT_01} -- 因为每天取得数据都是最新的数据,所以,stg表就是最新的数据 ; " runsql -sql "${V_SQL}" -msg "${V_MSG}" -engine hive -env hwCloud || return $?
-sql:要执行的sql语句
-msg:执行sql提示信息
-engine:选择执行引擎,这里目前可以选择hive和impala
-env: 执行环境
hwCloud:华为云
aliCloud:阿里云正式区
aliCloudTest: 阿里云测试区
azureCloud: 微软云
|| return $? : 获取代码执行状态
hive脚本案例可以查看DataWarehose/public/hive_templete.sh
impala脚本案例可以查看DataWarehose/public/impala_templete.sh
调度系统使用规范
- 工作流按照项目划分,理论上,一个项目的所有任务都在一个工作流内
- 一个job输出一个结果表,需要配置前置和后置依赖
- job名称统一按照时间粒度 + 输出结果表名来命名,例如offline_ods_pom_business_work_record,代表离线计算ods_pom_business_work_record
具体的项目案例,可以参考华为云上的pom项目
任务上线流程
- 代码在本地开发完成后,需统一提交到DataWarehose
- 经由管理员codeReview之后合并到master分支
- 在数据中台-项目管理-projectDeploy,选择相应的job执行代码分发