背景
目前,用户在Dataphin上进行数据开发时,风格各异,缺乏一致性。为此,我们整理了一份开发规范文档,旨在帮助所有用户实现更高效和一致的开发流程。文档主要涵盖在Dataphin中进行建表、创建节点、编写代码、节点配置等数据开发阶段的规范性指导。我们欢迎大家提出改进意见,以便共同优化。
- 以下开发规范分为三个等级:【强制】、【禁止】和【推荐】:
- 【强制】:必须遵循的规范
- 【禁止】:绝对不允许的做法
- 【推荐】:强烈建议遵循的规范,但比【强制】的要求稍弱
创建文件夹
- 【推荐】通过文件夹体现代码模块关系,按照高内聚低耦合的原则去组织文件夹及节点代码,文件夹名称建议使用易理解的中文
【正例】 如下图,在“安全性数据应用层”中,整体结构被划分为多个子模块。每个子模块可以进一步细分为若干文件夹,将强相关的节点文件组织在一起。文件夹使用中文命名,代码文件则使用英文命名,以提高可读性和便于管理
|
【反例】 如下图,所有财务相关的节点代码都被扁平化地放置在一个通用的“财务”文件夹中,没有按照预算、报告生成等功能进行模块化划分,并且使用了不清晰的缩写和不一致的命名方式,无法有效反映代码的内容和功能,增加了理解和管理的难度
|
新建表
- 【强制】表命名要遵守一定的命名规范
【正例】 按照既定命名规范去命名(例如OneData规范):
|
【反例】 随意命名,不符合通用的命名规范:
|
- 【强制】能用分区表的就不要用非分区表,数据加工中的物理表和逻辑表都应该使用分区表,可用ds作为业务日期分区。
【正例】 如下代码中用到的表都是分区表,将提升查询效率与数据管理的灵活性
|
【反例】 如下代码所示,使用非分区表会导致无法高效管理历史数据,并在删除重建期间数据不可用,同时难以追踪表的创建历史和版本变更
|
- 【强制】表注释及字段注释要完整清晰
【正例】 完整的字段注释,有助于在后续使用或逻辑变更过程中快速理解数据结构及代码逻辑
|
【反例】 当字段注释和表注释均为空时,增加了数据使用和运维的复杂性及成本
|
新建节点
- 【强制】节点名称和输出结果表名称保持一致并遵守一定的命名规范
【正例】 节点名称使用英文且和输出结果表保持一致,且遵守一定命名规范
|
【反例】 节点名称与输出结果表名称不一致,难以快速通过表名搜索到节点
|
命名规范参考如下:
节点、资源类型 |
命名规范 |
示例 |
虚拟节点 |
vt_{虚拟节点含义} |
vt_data_processing_root |
同步导入任务 |
imp_s_{表名} |
imp_s_customer_data |
同步导出任务 |
exp_{表名} |
exp_dws_sales_summary |
Shell节点 |
sh _{脚本命名} |
sh_log_archival |
MR节点 |
mr_{脚本命名} |
mr_transaction_analytics |
DDL 资源 |
{输出表名}.ddl |
fact_sales_data.ddl |
PYTHON 资源 |
{脚本命名}.py |
data_parser.py |
JAR |
{脚本命名}.jar |
DataProcessor.jar |
- 【建议】确保项目内节点名称唯一
【正例】 当节点名称符合规范且唯一,在运维管理时,可以清晰地看到每个节点,方便进行任务的管理和故障排查 |
【反例】 在Dataphin项目中,节点名称重复会导致管理混乱与操作混淆,增加日志记录和监控系统精准执行的难度,从而影响问题追踪与及时解决 |
- 【推荐】跨项目引用表时,表前添加项目前缀${项目名称}
【正例】 通过在引用表前添加项目前缀${项目名称},可以高效地在Dataphin中引用跨项目空间的表,提高开发效率和代码的可维护性 |
【反例】 跨项目引用的其他方法虽然提供了灵活性和动态性,但也带来了代码冗余、任务依赖性强和调试困难等问题 |
SQL代码编写规范
- SQL代码编写原则:
- 代码清晰整齐:保持代码行对齐,使用一致的缩进和格式,以提高可读性。
- 幂等性:设计每个节点保证多次执行结果一致,即节点可以安全地重跑而不会影响最终结果。
- 结构化和层次分明:组织代码逻辑清晰,模块化设计,便于理解和维护。
- 注释完善:在代码中添加必要的注释,解释复杂逻辑和关键步骤,以增强代码的可读性。
- 性能优化:编写代码时考虑执行效率,优化查询速度,避免不必要的复杂操作。
- 安全性:确保数据处理遵循安全标准,防止SQL注入等安全漏洞。
- 可维护性:结构化代码以便于后续的修改和扩展,遵循命名规范和最佳实践。
- 【推荐】代码头部添加必要的注释信息,例如所属主题或数据源、功能描述、创建者、修改信息
【正例】 注释信息和方案文档的URL地址能显著提升代码的可维护性。我们编写的代码不仅为自己服务,还将在生产环境中由他人接手维护。因此,代码的可维护性至关重要。
|
【反例】 代码头部注释信息不足,若后续由他人维护且无相关文档,将难以理解与维护
|
- 【强制】使用行缩进模式,使得代码块结构更清晰,可以使用Dataphin的格式化工具自动格式化
【正例】 代码通过适当的缩进增强可读性
|
【反例】 该代码片段未有效使用行缩进模式,且代码结构不清晰、缩进不一致、缺乏注释和逻辑分段,增加了代码的阅读和维护难度
|
- 【禁止】禁止在insert语句中使用Project名称作为表名前缀
【正例】 在 |
【反例】 在 |
- 【禁止】禁止使用
INSERT INTO TABLE
语句,而用INSERT OVERWRITE TABLE
语句
【正例】 使用 |
【反例】
|
- 【禁止】避免使用
CREATE TABLE table_name AS
语句,而应采用分区表。
【正例】 使用分区表,向特定分区插入数据
|
【反例】
|
- 【禁止】最外层SELECT禁止使用SELECT *操作,而要需要明确指定需要的字段
【正例】 明确指定SELECT的字段,有助于提高查询性能、增强代码可读性,并且防止因表结构变化导致的潜在错误
|
【反例】 使用
|
- 【推荐】SELECT关键字后的字段之间的逗号(,)分隔符放在字段的前面,而不是字段后面
【正例】 将逗号置于字段之前,不仅使格式更为整洁,还在注释或删除尾部字段时更加便捷,无需单独处理上一行的逗号
|
【反例】 若需删除或注释掉
|
- 【强制】字段来自多个子查询时,应在SELECT关键字后的字段前加上子查询的别名
【正例】 在SELECT语句中,为每个字段添加子查询别名(如:b1.field_name),可显著提高代码的可读性,并便于快速识别字段来源
|
【反例】 在SELECT语句中,若字段前未使用子查询别名(例如:仅写field_name),特别是在字段名重复或子查询较多时,会导致字段来源难以辨识,增加理解难度和错误风险
|
- 【强制】在处理多层嵌套子查询时,可以通过简单的字符别名来体现层次关系。
【正例】 使用简单字符别名可使SQL语句中的字段引用更加便捷,并通过别名体现层次关系,使代码结构更清晰、易于理解。必要时,为别名添加注释以增强可读性。
|
【反例】 子查询中使用了简单字符别名和复杂或无意义的别名,缺乏层次关系,导致代码难以维护和理解,特别是在多层嵌套时。
|
- 【强制】避免在周期性任务节点代码前放置建表语句
【正例】 通过分离建表语句与调度逻辑,可显著提升数据处理的效率和性能。初期单独执行建表操作确保了表结构的存在,使调度节点代码(周期性任务)专注于数据处理,避免重复建表 |
【反例】 在调度节点代码前放置建表语句会导致资源和时间的浪费。每次运行调度节点时,都会生成ODPS实例来执行建表操作,消耗集群资源。此外,重复执行建表语句会增加任务的执行时间,尤其在大规模数据处理场景中更为明显 |
- 【禁止】避免将子查询的过滤条件置于连接条件或连接之后,应将其放在子查询内部
【正例】 针对子查询的过滤条件都放在了子查询内部,符合“高内聚”原则
|
【反例】 该代码将子查询b的过滤条件
|