6 月份的大部分时间在完成一个特殊的数据迁移工具, 将文件中的标签整合到关系型数据库的表字段中. 从近几年的技术趋势和参与的项目看, 基本都是从关系型数据库往大数据组件迁移. 在这个项目中, 主要是客户和相关应用的供应商依赖于 PostgreSQL 的 GIS 插件. 因此我也有幸使用了一次 PostgreSQL 数据库. 本文简要讲解了工具开发的背景和难点, 并给出了程序逻辑和源代码链接.
01 需求和背景
a). 为什么说这是一个字段级别的迁移?
作为数据源的标签文件数量非常多, 根据标签的分类和加工的便利程度, 有大量含有各位数据标签列的文件. 而同时在 PG 库表中, 为了减少 join, 提升数据库查询速度, 大量标签字段又合在一张表中. 结果就是存在, 一个文件的不同列可能映射到不同的表中, 一张表的不同字段来自于不同的文件. 文件和表存在的是多对多的关系. 这就造成不能简单地做出某个文件到某张表的映射关系, 然后使用导入工具导入即可.
同时, 对于客户和使用者而言, 他们希望看到的是就是标签值(即对应数据库中的字段). 通过展示标签级别的映射关系, 最终用户可以知晓每个标签的业务含义和数据来源; 通过展示每个标签的加工状态, 管理员可以快速获取整体标签的可用性.
最后, 数据源结构上是半结构化的 CSV 文件, 列的数量和存放顺序可能发生改变. 文件和表的将是动态的, 维护起来的工作量也过于巨大.
b). 开发中依赖的一些业务说明
首先, 对于标签类数据的存放表, 认为是有业务主键的, 这些主键也是其他应用查询数据时的条件. 程序中使用这些主键来完成新标签数据的插入和旧标签数据的更新.
对于明细类数据, 数据源的定义认为是没有主键的日志类数据, 只有插入的操作无更新的操作.
同时, 标签的更新方式还分为增量和全量. 增量即常规的 merge 操作, 而全量方式需要将表中的指定标签字段置空后再进行 merge 操作.
02 遇到的问题和解决方法
a). 文件的导入和并发控制
虽然每一个任务都是字段级别操作的, 但是对于数据源文件的导入存在多个标签对应同一源文件的情况, 所以在文件导入操作上有一个专门的状态表记录文件导入的状态. 如果有其它标签任务在执行相同的文件导入了, 状态就会变成 processing. 作为一个后来的任务, 必须等待状态为 success 或者 fail 时才能进行文件的再次导入.
同时为了避免文件的再次导入, 每次导入还会比较 HDFS 中文件的时间戳和状态表中的时间戳, 如果时间戳一致, 则直接使用已导入的文件即可.
b). 文件的动态入库
CSV 文件的首行列名作为字段名, 文件名作为表明在临时库创建一张临时表, 然后使用 copy_expert 函数避免双引号分界符内容中存在逗号的问题.
c). 明细和标签的整合
为了让两者使用同一套字段级别的 merge 方法, 对于明细的数据在传到本地文件系统后, 调用 shell 命令根据每一行的内容加行号 md5 hash 之后作为一行明细的主键. 从而每一行数据都是唯一的, 保证了数据在调用 merge 操作时只有 insert 行为.
d). 派生字段的处理
来源: https://www.cnblogs.com/shenfeng/p/tag_level_etl_tool.html