[NewLife.XCode]扩展属性(替代多表关联Join提升性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode。
整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含多年开发经验于其中,代表作有百亿级大数据实时计算项目。
开源地址:https://github.com/NewLifeX/X(求star, 743+)
为何需要扩展属性
XCode不支持多表关联查询,单表查询利于优化以及分表分库,一切Join都可以借助扩展属性实现,配合缓存使用可以达到更好的效果!
(XCode前期支持多表关联,直到2008年才正式废除)
“扩展属性”是2007年起XCode特有叫法,不同于其它任何场景的意义(如Silverlight/WPF)
前文《实体类详解》中有提到一个学生班级的实体类模型,一个典型需求是查询学生列表时希望暂时班级名称或者其它信息。于是有:
select s.*, c.name where student s left join class c on s.classid=c.id
sql语法千变万化,如果要支持多表关联join,就很难做到统一查询风格,更是难以优化。
于是XCode放弃支持多表关联,宁可拆分为多次查询。令人惊讶的是,不仅性能没有下降,反而大大提升了,主要因为单表小查询有多级缓存的加持!
扩展属性用法
使用扩展属性来实现关联查询,本质上就是多次查询!
如上,这是一个经典的多表关联场景,学生表带有班级ID字段,同样还有产品和分类表等等。
这是XCode根据模型文件自动生成的代码,因为字段名ClassID刚好是Class表加上它的主键ID,并且都是整型。
对于实体对象来说,student.Name是学生名称,student.ClassName是班级名称。
看起来它们就像是一张表的属性字段,这就是扩展属性的由来,不仅仅是多表关联属性,还可以是其它属性,为区别于数据字段属性,统称为扩展属性!
扩展属性先准备一个Class属性,再加一个ClassName,主要是为了方便某些场合使用 student.Class。
当然,执行一次查询得到student后,不论是访问student.Class还是访问student.ClassName,都会触发一次Class.FindByID,可以理解为执行一次查询(不一定是数据库)。
在Web页面上,如果每页显示20个学生,那么先要执行 select * from student limit 20,然后展示学生列表时,因为需要班级名称,触发扩展属性查询。
可以认为,理论上这个页面需要查询1+20次。
扩展属性为什么不写成 public Class Class => Class.FindByID(ClassID) 呢?
其实虽然看起来简单,但是还得考虑一个可能,同一个student对象可能多次访问student.ClassName,这么写岂不是每次访问都会执行Class.FindByID?
因此,XCode设计了扩展集合Extends,可以认为是一个字典,每个扩展属性都经过它走一遭,如果查询过一次就缓存起来,避免反复查询。
Extends.Get第一个属性是扩展属性名,决定是否有缓存,第二个是没有缓存时要执行的委托。
这就是扩展属性缓存,默认缓存时间10秒,足够抗住短期内成千上万次重复调用。
扩展属性优化
尽管有Extends扩展属性缓存支持,但每个对象还是要执行一次Class.FindByID查询,损耗还是不小的。
在XCode里面,根据主键而设计的查询(如FindByID)往往带有很好的缓存优化。
如上,这是XCode默认生成的代码,当Class表数据不足1000行时,走实体缓存。
也就是说,Meta.Cache时执行一次 select * from student 返回所有行,并缓存起来。后面的Find实际上是在缓存中查找。实体缓存有效期默认10秒。
只有数据表达到1000行,才走 Find(_.ID==id) 数据库查询 select * from class where id=? 。然而XCode下层还有一个数据层缓存,相同select查询默认缓存10秒
此外,也可以根据业务特点采用单对象缓存,例如跨境电商的产品种类特别多(10万+),可以采用字典式的单对象缓存。
因此,在学生类那边看起来访问属性会触发多次Class.FindByID,殊不知它内部别有洞天,三级缓存(实体缓存、对象缓存、数据缓存)等着伺候!(后续专文介绍缓存)
回到开头的例子,一个列表页显示20个学生,理论查询次数1+20次,在多级缓存加持的扩展属性下,99.99%的时候只会查询1次,而班级表的关联,完全在内存缓存中进行。
一次简单的单表查询,显然要比join班级表的查询要快得多!
魔方的特别支持
在上述扩展属性中,注意到ClassName属性上有一个Map特性。
它表示映射,本对象的ClassID字段,映射到Class类的ID字段。
在魔方列表页中,本来显示冷冰冰ClassID的地方,就会变为显示友好的ClassName。
在魔方表单页中,本来显示数字框ClassID的地方,也会变成显示下拉列表框。
如果下拉列表库内容很多,可以精简Map特性,只要第一个参数指明本地字段,而不需要第二第三字段表示的目标字段。此时在魔方表单页会显示数字框,但是后面显示ClassName
到此,你还认为多次查询一定比单次Join慢吗?
系列教程
NewLife.XCode教程系列[2019版]
- 增删改查入门。快速展现用法,代码配置连接字符串
- 数据模型文件。建立表格字段和索引,名字以及数据类型规范,推荐字段(时间,用户,IP)
- 实体类详解。数据类业务类,泛型基类,接口
- 功能设置。连接字符串,调试开关,SQL日志,慢日志,参数化,执行超时。代码与配置文件设置,连接字符串局部设置
- 反向工程。自动建立数据库数据表
- 数据初始化。InitData写入初始化数据
- 高级增删改。重载拦截,自增字段,Valid验证,实体模型(时间,用户,IP)
- 脏数据。如何产生,怎么利用
- 增量累加。高并发统计
- 事务处理。单表和多表,不同连接,多种写法
- 扩展属性。多表关联,Map映射
- 高级查询。复杂条件,分页,自定义扩展FieldItem,查总记录数,查汇总统计
- 数据层缓存。Sql缓存,更新机制
- 实体缓存。全表整理缓存,更新机制
- 对象缓存。字典缓存,适用用户等数据较多场景。
- 百亿级性能。字段精炼,索引完备,合理查询,充分利用缓存
- 实体工厂。元数据,通用处理程序
- 角色权限。Membership
- 导入导出。Xml,Json,二进制,网络或文件
- 分表分库。常见拆分逻辑
- 高级统计。聚合统计,分组统计
- 批量写入。批量插入,批量Upsert,异步保存
- 实体队列。写入级缓存,提升性能。
- 备份同步。备份数据,恢复数据,同步数据
- 数据服务。提供RPC接口服务,远程执行查询,例如SQLite网络版
- 大数据分析。ETL抽取,调度计算处理,结果持久化
[NewLife.XCode]扩展属性(替代多表关联Join提升性能)的更多相关文章
- Hive中小表与大表关联(join)的性能分析【转】
Hive中小表与大表关联(join)的性能分析 [转自:http://blog.sina.com.cn/s/blog_6ff05a2c01016j7n.html] 经常看到一些Hive优化的建议中说当 ...
- [NewLife.XCode]反向工程(自动建表建库大杀器)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
- SQL学习(五)多表关联-join
在实际工作中会用到多表联查,此时需要用到关键字JOIN 一.inner join(内连接) 至少有一个匹配时返回行,只返回两个表中连接字段相等的行 如: select * from ticket in ...
- [NewLife.XCode]分表分库(百亿级大数据存储)
NewLife.XCode是一个有15年历史的开源数据中间件,支持netcore/net45/net40,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量 ...
- [NewLife.XCode]数据模型文件
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]实体类详解
NewLife.XCode是一个有10多年历史的开源数据中间件,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和运行日志来进行深入分析,蕴含 ...
- [NewLife.XCode]高级查询(化繁为简、分页提升性能)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- [NewLife.XCode]对象字典缓存(百万军中取敌首级)
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...
- [NewLife.XCode]高级增删改
NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netstandard,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示 ...
随机推荐
- MongoDB + Express 环境搭建记
最近项目需要使用 MongoDB,所以不得不搭建 MongoDB 环境,此文记录搭建过程及使用过程中需要了解的问题. Linux + Windows 混合搭建调试 MongoDB 记录 版本介绍 : ...
- PHP中this,self,parent的区别
{一}PHP中this,self,parent的区别之一this篇 面向对象编程(OOP,Object OrientedProgramming)现已经成为编程人员的一项基本技能.利用OOP的思想进行P ...
- 20155205 郝博雅 Exp5 MSF基础应用
20155205 郝博雅 Exp5 MSF基础应用 一.实验目标 本实践目标是掌握metasploit的基本应用方式,重点常用的三种攻击方式的思路.具体需要完成: 1.一个主动攻击实践,如ms08_0 ...
- 海龟绘图turtle库之二级基础编程题
一.画一个太极图 import turtle as t t.pensize(2)#设置笔画宽度 t.circle(100)#以100为半径的圆 t.circle(50, 180) t.circle(- ...
- 如何下载官网上下载历史Java版本(老版本Java)
首先先打开Oracle的官网 -->Oracle 然后选择Trials and Downloads 然后往下翻,选择java(JDK) 然后看到了这个,再往下翻 点他,然后就是选择你想下载 ...
- 团队-Forward团队-团队一阶段互评
团队名称:Forward团队 学号:2015035107105 得分:7 原因:知识欠缺,能够一边学一边做 学号:2015035107109 得分:6 原因:对我有很多帮助 学号:2015035107 ...
- Windows下安装BeautifulSoup4显示'You are trying to run the Python 2 version of Beautiful Soup under Python 3.(`python setup.py install`) or by running 2to3 (`2to3 -w bs4`).'
按照网上教程,将cmd的目录定位到解压缩文件夹地址,然后 >>python setup.py install ( Window下不能直接解压tar.giz文件,可以使用7z解压软件提取解压 ...
- 最近一个dish项目的建设思考
系统通用能力的沉淀:a.核心模型的数据沉淀 b.通用服务能力的沉淀 ps1:以前重心主要放在了业务的抽象和通过设计模式来增加可复用的扩展性.局限在于,抽象的范围会被单个业务或者当前的业务所束缚,在更大 ...
- 实现一个simple 3层的神经网络
1.基本概念 1.1softmax softmax函数:一句话概括:是logistic 函数的扩展,将一个p维的数值向量映射成为一个k维的概率值,且这k个值的和为1. 公式: 解释: 1.2 cros ...
- .Net程序员 初学Ubuntu ,配置Nignix
1.安装VM虚拟机 2.升级VI编辑器 3.安装Nginx 4.测试localhost 5.编辑配置文件 仅仅用了记录一个过程,不会太详细 1.安装虚拟机,网上一大片,不是特别难 2.为什么要升级VI ...