继国庆节 SmartCode 正式版(SmartCode.Generator)发布之后,SmartCode 迎来了新的能力 SmartCode.ETL !
SmartCode 正式版从开始发布就从未说过自己仅仅是个代码生成器,这点上从我第一次宣布SmartCode正式开源的文章就可以说明:《SmartCode 不只是代码生成器》,这不仅仅是一句推广语!
相信不少同学都用过各种代码生成器,这里我就不做详细介绍了,如果想体验 SmartCode.Generator 请至 https://www.cnblogs.com/Ahoo-Wang/p/SmartCode-intro.html 配置好数据库连接,一键生成解决方案。
相信不少已经落地微服务架构方案的同学都会遇到同样的问题:
业务方的查询需求似乎总是跨微服务DB的
领导层需要查看的报表数据总是全局的(需要聚合跨微服务DB的)
从多个微服务DB 同步业务聚合查询数据到 all_biz DB (解决:微服务架构一定会遇到的业务方需要跨微服务DB查询的问题)
从 all_biz DB 同步聚合分析数据到 report DB (解决:领导层查看的报表数据聚合问题)
安装 SmartCode from dotnet-cli
dotnet tool install --global SmartCode.CLI
使用 SmartCode.Generator 生成 同步Sql表结构脚本,以及 SmartCode.ETL 构建配置
执行Sql同步脚本初始化表结构
使用任务调度(crontab) + SmartCode.ETL 同步分析数据
通过持久化 etl_task 监控 etl执行情况(目前支持PostgreSql)
简单来说就是SmartCode生成SmartCode,任务调度执行SmartCode命令行。(这真的不是先有鸡还是蛋的问题.....)
{ "SmartCode": { "Version": "v1.16.15", "Plugins": [ { "Type": "SmartCode.IDataSource,SmartCode", "ImplType": "SmartCode.NoneDataSource,SmartCode" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.App.BuildTasks.ClearBuildTask,SmartCode.App" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.App.BuildTasks.ProjectBuildTask,SmartCode.App" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.App.BuildTasks.MultiTemplateBuildTask,SmartCode.App" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.App.BuildTasks.ProcessBuildTask,SmartCode.App" }, { "Type": "SmartCode.IOutput,SmartCode", "ImplType": "SmartCode.App.Outputs.FileOutput,SmartCode.App" }, { "Type": "SmartCode.IDataSource,SmartCode", "ImplType": "SmartCode.Generator.DbTableSource,SmartCode.Generator" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.Generator.BuildTasks.TableBuildTask,SmartCode.Generator" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.Generator.BuildTasks.SingleBuildTask,SmartCode.Generator" }, { "Type": "SmartCode.INamingConverter,SmartCode", "ImplType": "SmartCode.Generator.TableNamingConverter,SmartCode.Generator" }, { "Type": "SmartCode.TemplateEngine.ITemplateEngine,SmartCode.TemplateEngine", "ImplType": "SmartCode.TemplateEngine.Impl.HandlebarsTemplateEngine,SmartCode.TemplateEngine" }, { "Type": "SmartCode.TemplateEngine.ITemplateEngine,SmartCode.TemplateEngine", "ImplType": "SmartCode.TemplateEngine.Impl.OfficialRazorTemplateEngine,SmartCode.TemplateEngine" }, { "Type": "SmartCode.Generator.IDbTypeConverter,SmartCode.Generator", "ImplType": "SmartCode.Generator.DbTypeConverter.DefaultDbTypeConverter,SmartCode.Generator" }, { "Type": "SmartCode.IDataSource,SmartCode", "ImplType": "SmartCode.ETL.ExtractDataSource,SmartCode.ETL" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.ETL.BuildTasks.TransformBuildTask,SmartCode.ETL" }, { "Type": "SmartCode.ETL.ITransformEngine,SmartCode.ETL", "ImplType": "SmartCode.ETL.TransformEngine.RazorTransformEngine,SmartCode.ETL" }, { "Type": "SmartCode.IBuildTask,SmartCode", "ImplType": "SmartCode.ETL.BuildTasks.LoadBuildTask,SmartCode.ETL" }, { "Type": "SmartCode.ETL.IETLRepository,SmartCode.ETL", "ImplType": "SmartCode.ETL.NoneETLRepository,SmartCode.ETL" }, { "Type": "SmartCode.ETL.IETLRepository,SmartCode.ETL", "ImplType": "SmartCode.ETL.PostgreSql.PGETLRepository,SmartCode.ETL.PostgreSql", "Paramters": { "ConnectionString": "Server=localhost;Port=5432;User Id=postgres;Password=SmartSql; Database=smartcode_etl;" } } ] } }
Author: Ahoo Wang DataSource: Name: Extract Paramters: DbProvider: SqlServer ConnectionString: Data Source=.;Initial Catalog=SmartSqlDB;Integrated Security=True Query: SELECT [Id],[UserName],[Status],[LastLoginTime],[CreationTime],[ModifyTime],[Deleted] FROM [T_User] With(NoLock) Where ModifyTime>@LastMaxModifyTime PKColumn: Id AutoIncrement: true ModifyTime: ModifyTime Paramters: ETLCode: SmartCode.ETL.Test ETLRepository: PG Build: Transform: Type: Transform Paramters: Script: Load2PostgreSql: Type: Load Paramters: DbProvider: PostgreSql ConnectionString: Server=localhost;Port=5432;User Id=postgres;Password=SmartSql; Database=smartsql_db; Table: t_user__temp PreCommand: CREATE TABLE t_user__temp( LIKE t_user ); PostCommand: "Delete From t_user as source Where EXISTS(select * from t_user__temp temp where temp.id=source.id); Insert Into t_user SELECT * From t_user__temp; Drop Table t_user__temp; " ColumnMapping: [{Column: Id,Mapping: id} ,{Column: UserName,Mapping: user_name} ,{Column: Status,Mapping: status} ,{Column: LastLoginTime,Mapping: last_login_time} ,{Column: CreationTime,Mapping: creation_time} ,{Column: ModifyTime,Mapping: modify_time} ,{Column: Deleted,Mapping: deleted}]
参数名 | 说明 |
---|---|
ETLCode | ETL任务Code,区分任务类型,唯一 |
ETLRepository | ETL任务持久化仓储,None/PG |
属性 Name:Extract,使用 ExtractDataSource 插件作为数据源
参数名 | 说明 |
---|---|
DbProvider | 数据驱动提供者:MySql,MariaDB,PostgreSql,SqlServer,Oracle,SQLite |
ConnectionString | 连接字符串 |
Query | 查询命令,需要抽取的数据。默认会自动注入三个参数 LastMaxId,LastMaxModifyTime,LastQueryTime 作为查询条件 |
PKColumn | 主键列名 |
AutoIncrement | 是否为自增主键,true 自动计算抽取的最大主键值(MaxId) |
ModifyTime | 最近一次修改时间列名,设置后自定计算抽取的最大修改时间列(MaxModifyTime) |
属性 Type:Load,使用 LoadBuildTask 插件作为构建任务
参数名 | 说明 |
---|---|
DbProvider | 数据驱动提供者:MySql,MariaDB,PostgreSql,SqlServer,Oracle,SQLite |
ConnectionString | 连接字符串 |
Table | 目标表名 |
PreCommand | 执行批量插入任务之前执行的命令 |
PostCommand | 执行批量插入任务之后执行的命令 |
ColumnMapping | 列映射 |
LastMaxId 即上一次抽取的数据最大Id值(第一次抽取时LastMaxId为-1),该模式使用于数据插入后不再变更的数据表。
LastMaxModifyTime 即上一次抽取的数据最大ModifyTime值(第一次抽取时LastMaxModifyTime为1970-01-01 08:00:00),适用于插入数据后还会变更的数据表。
对 Id 取模,分拆不同任务,同时并发执行
使用 Top/Limit 限制数据抽取数量,分多次同步执行完成整个数据同步。
运行环境
源抽取库:Windows Server 2012 , 8 vCPU 16 GB + SSD + SqlServer-2014
目标分析库:CentOS-7 , 8 vCPU 16 GB + SSD + PostgreSql-11 + SmartCode
ETL_Task.Extract
以下是数据抽取性能,抽取数量为 1434678,耗时 41267 毫秒。
{ "MaxId": 1755822, "PKColumn": "Id", "QuerySize": 1434678, "QueryTime": "2018-11-01T11:31:53.6191084+08:00", "QueryCommand": { "Taken": 41267, "Command": "Select * From T_ProductSearchLog With(NoLock) Where Id>@LastMaxId", "Paramters": { "LastMaxId": -1, "LastQueryTime": "1970-01-01T08:00:00", "LastMaxModifyTime": "1970-01-01T08:00:00" } } }
ETL_Task.Load
以下是数据加载性能,批量插入数据量为 1434678,耗时 21817 毫秒,平均每秒插入 65759.6 条数据。
{ "Size": 1434678, "Table": "t_product_search_log", "Taken": 21817, "PreCommand": null, "PostCommand": null }
目前 SmartCode.ETL 已经落地到我们的生产环境了(11-01上线截至 2018-11-16 16:50 执行了 65520 次同步任务,暂无error日志抛出)
PS: 虽然 SmartCode.ETL 只花了周末俩天时间完成扩展,但已经可以满足我们至少90%的应用场景。这足以见得 SmartCode 扩展能力是多么令人意外了。当然SmartCode的其他能力还得后续等各位一起发掘!!!
SmartCode 常见问题 SmartCode 能干什么? SmartCode = IDataSource -> IBuildTask -> IOutput => Build Everything SmartCode的执行流是 数据源->构建任务->输出,也就是说应用场景非常广泛。 从DB读取数据结构,最终生成整个解决方案=代码生成器(SmartCode.Generator) ETL,其实很显然
扩展是专门设计的在 Yii 应用中随时可拿来使用的, 并可重发布的软件包。例如, yiisoft/yii2-debug 扩展在你的应用的每个页面底部添加一个方便用于调试的工具栏, 帮助你简单地抓取页面生成的情况。 你可以使用扩展来加速你的开发过程。 信息: 本文中我们使用的术语 "扩展" 特指 Yii 软件包。而用术语 "软件包" 和 "库" 指代非 Yii 专用的通常意义上的软件包。 使用扩展
vscode-react-native vscode-go
扩展为现有的类、结构体、枚举类型、或协议添加了新功能。这也包括了为无访问权限的源代码扩展类型的能力(即所谓的逆向建模)。扩展和 Objective-C 中的分类类似。(与 Objective-C 的分类不同的是,Swift 的扩展没有名字。) Swift 中的扩展可以: 添加计算实例属性和计算类型属性; 定义实例方法和类型方法; 提供新初始化器; 定义下标; 定义和使用新内嵌类型; 使现有的类型遵
概述 范例-hello-world 范例-word-count 范例-language-server 范例-调试器 调试-扩展 安装-扩展 范式-原则 测试-扩展 用我们的方法创造扩展
本页包含内容: 扩展语法 计算型属性 构造器 方法 下标 嵌套类型 扩展就是向一个已有的类、结构体或枚举类型添加新功能(functionality)。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。扩展和 Objective-C 中的分类(categories)类似。(不过与Objective-C不同的是,Swift 的扩展没有名字。) Swift 中的扩展可以: 添加计算型属
Jinja2 支持扩展来添加过滤器、测试、全局变量或者甚至是处理器。扩展的主要动力是 把诸如添加国际化支持的常用代码迁移到一个可重用的类。 添加扩展 扩展在 Jinja2 环境创建时被添加。一旦环境被创建,就不能添加额外的扩展。要添加 一个扩展,传递一个扩展类或导入路径的列表到 Environment 构造函数的 environment 参数。下面的例子创建了一个加载了 i18n 扩展的 Jinj
一、本功能块说明 1.功能块简介 本功能块主要集中了全站各个模块的一些扩展属性,能够更加直观快速的进入所需的功能页面! 二、术语约定 1.导航栏 在本功能块下 导航栏 统一指整站的头部导航,既如下图所示: 2.菜单栏 在本功能块下 菜单栏 统一指扩展导航栏下的左侧菜单,既如下图所示:
http2协议强制规定了接收方必须读取并忽略掉所有未知帧(即未知帧类型的帧)。双方可以在逐跳原则(hop-by-hop basis)基础上协商使用新的帧,但这些帧的状态无法被改变,也不受流控制。 是否应该允许添加扩展的这个话题在制定http2协议的时候被反复讨论了很久,但在draft-12之后,最终尘埃落定确定了允许添加扩展。 但扩展不再是协议本身的一部分,它被记录在核心协议规范之外。现在已经有两