[NewLife.XCode]脏数据

NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。

整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。

开源地址:https://github.com/NewLifeX/X(求star, 729+)

什么是脏数据

在XCode中,每次执行实体类更新entity.Update时,都希望只更新修改过的字段,而不是update所有字段

一方面,减少数据库压力以及通信流量;

另一方面,多线程同时更新同一行数据的不同字段,在未加锁的情况下,避免脏写。

[NewLife.XCode]脏数据

IsDirty和Dirtys,这是XCode的脏数据,常常出现在Valid中 。

如上图,前者判断Password字段是否有脏数据(Password被赋予跟原来不想等的值),后者清空Password脏数据。

脏数据是生成Update语句的核心,不脏的字段不会出现在update set 之中,从而实现部分字段更新。

设置脏数据

脏数据是XCode实体类内置功能,每一个实体类属性set操作中都带有脏数据逻辑。

[NewLife.XCode]脏数据

实体类属性并非普通属性,而是带有OnPropertyChanging逻辑

[NewLife.XCode]脏数据

这里是脏数据的默认设置点,先比较新旧值是否一致,如果一致,显然不会设置脏数据。

实体属性数值是否相等比较逻辑:

  • 整数全部转换为Int64比较,避免因类型不同而误判
  • 时间日期只比较年月日时分秒,而不比较毫秒等其它部分
  • 字符串比较时,null与empty相等
  • 浮点数比较(单精度和双精度),比较到小数点后6位
  • Decimal比较到小数点后12位

使用代码来表达,大概是下面的样子:

[NewLife.XCode]脏数据

实体类属性赋值有三种方法:

  • user.Password = "Stone"
  • user.SetItem("Password", "Stone")
  • user["Password"] = "Stone"

主要功能相似,都是给Password字段赋值。

最大的不同点在于:后者一定不会设置脏数据,仅仅是简单赋值;前面两个可能会设置脏数据,要求Password原值不等于"Stone"时才会设置脏数据。

* SetItem就是第一种强类型脏数据和第三种弱类型赋值两者优点的混合体!

脏数据效果

[NewLife.XCode]脏数据

Update User Set Mobile='', Code='abcdef' Where ID=74

如上,修改了3个字段,但是Name本来就是“张三”,因此实际上只修改了两个字段,也就是说只有两个字段有脏数据(数值改变被弄脏了)。

最终生成的update set语句,只包含带有脏数据的字段。最后的where部分,则由主键组成。

使用脏数据

脏数据最常见于数据验证Valid中,可以用来判断某个属性否则曾经被修改过

[NewLife.XCode]脏数据

如上,两次用到脏数据,如果业务代码没有设置用户名或创建时间,则在Valid时设置。

因此,脏数据往往用于给字段设置默认值。除了可用于实体类Valid,还可以用于实体过滤器EntityModule.Valid。

判断脏数据有两种办法 Dirtys["CreateTime"] 和 IsDirty("CreateTime") 。上面的__.CreateTime实质上就是"CreateTime"常量,仅仅是为了避免用户写错单词。

在大数据分析处理场合,数百万实体对象位于内存之中,Dirtys将导致每个实体对象附带实例化一个脏数据集合对象,而IsDirty则不会,因此效果更好。

实现原理

第一代脏数据实现就是字典 Dictionary<String, Boolean>,后来发现在高并发性频繁出现多线程冲突;

第二代脏数据实现是并行字典ConcurrentDictionary<String, Boolean>,后来在大数据分析处理中发现,单个并行字典,哪怕是空的,也要占用约2k内存空间;

第三代脏数据实现 DirtyCollection,采用了内置数组以及CAS原子操作,拥有最好的性能以及最小内存占用。

系列教程

NewLife.XCode教程系列[2019版]

  1. 增删改查入门。快速展现用法,代码配置连接字符串
  2. 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)
  3. 实体类详解。数据类业务类,泛型基类,接口
  4. 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置
  5. 反向工程。自动建立数据库数据表
  6. 数据初始化。InitData写入初始化数据
  7. 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)
  8. 脏数据。如何产生,怎么利用
  9. 增量累加。高并发统计
  10. 事务处理。单表和多表,不同连接,多种写法
  11. 扩展属性。多表关联,Map映射
  12. 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计
  13. 数据层缓存。Sql缓存,更新机制
  14. 实体缓存。全表整理缓存,更新机制
  15. 对象缓存。字典缓存,适用用户等数据较多场景。
  16. 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存
  17. 实体工厂。元数据,通用处理程序
  18. 角色权限。Membership
  19. 导入导出。Xml,Json,二进制,网络或文件
  20. 分表分库。常见拆分逻辑
  21. 高级统计。聚合统计,分组统计
  22. 批量写入。批量插入,批量Upsert,异步保存
  23. 实体队列。写入级缓存,提升性能。
  24. 备份同步。备份数据,恢复数据,同步数据
  25. 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版
  26. 大数据分析。ETL抽取,调度计算处理,结果持久化
上一篇:机器学习: 变分自编码器VAE


下一篇:iOS 纯代码适配iPhone6,6+