[NewLife.XCode]高级查询(化繁为简、分页提升性能)

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

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

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

 

回到目录

扩展查询

前文《[NewLife.XCode]实体类详解》中有讲到扩展查询,XCode生成实体类代码时,在模型类有一个region叫“扩展查询”,一般是FindByAbc/FindAllByAbc的形式。

扩展查询以数据表索引为依据来生成:

  • 唯一索引(含主键)生成FindByAbc方法(如FindByName),返回单个对象;

  • 非唯一索引生成FindAllByAbc方法(如FindAllByClassID),返回对象列表(非null);

640?wx_fmt=png

如上图,可知Entity实体基类内部,查询方法分为单对象查询的Find和对象列表的查询FindAll。

实际上,Find最终调用FindAll方法查一行。

 

Find/FindAll有多个重载,最主要的地方都是构造where查询条件。

下划线_是每个实体类都有的内嵌类,它包含了每一个字段的Field引用,借助运算符重载,可以很方便的构造查询条件,例如上面的_.Name == name最终会生成 where Name='Stone'

640?wx_fmt=png

因为是内嵌类,在实体类内部使用的时候非常方便。但要是想要实体类外部使用,就麻烦很多了,需要带上实体类类名。

 

原则:XCode是充血模型,不管多么简单的查询,建议都封装Find/FindAll/Search等方法供外部使用。

 

回到目录

高级表达式查询

仅靠一两个字段的简单查询,肯定无法满足各种业务要求,我们需要更强大的查询支持,特别是根据不同条件拼接不同语句。

640?wx_fmt=png

640?wx_fmt=png

上面是两个非常典型的业务查询。

这里请出了条件表达式WhereExpression,实际上它只有两个功能,&表示And,|表示Or,根据表达式级别支持括号运算。

exp&=xxx 是最常用的写法,右边一般是各种Field表达式。

上面第一个例子,生成的查询语句可能是 select * from Student where classid=?classid and name like '%?key%'

为什么说“可能”?因为classid为0,或者key为空时,并不会参与拼接查询语句。

 

第二个例子稍微复杂一些,首先对key进行精确查询,找到了就返回,若是没找到,则开启模糊查询。

这里遇到了等于、包含、区间等判断操作,后面会详解所有支持的操作。

 

如非必要,建议保留select * 的查询方式,而不是指定列。

码农法则:数据库压力小于100qps时不要考虑指明select列来优化,大多数系统活不到需要优化的明天!

 

回到目录

高级分页 

两个例子都出现了一个PageParameter参数page,这是分页参数,包含分页查询以及排序所需要的数据。

640?wx_fmt=png

PageIndex和PageSize指定页序号和每页大小,这是内部建立分页查询的核心依据;

Sort 指定排序字段,Desc 指定是否降序(默认升序);

RetrieveTotalCount 指定是否或者总记录数,若为true,则在查询记录集之前,先查询满足条件的总行数TotalCount,用于分页PageCount。此时等于执行两次数据库查询;

RetrieveState 指定是否获取统计 State,若为true,则在查询记录集之后,执行聚合查询,对数字型字段使用Sum聚合。此时最多可能执行3次数据库查询;

在执行FindAll查询时,若有传入 PageParameter 且 RetrieveTotalCount 为true,则先查询满足条件的记录数,大于0时才查某一页数据。

如果 Meta.Count 评估认为本表总行数超过100万,且FindAll查询没带有条件,则page.TotalCount直接取Meta.Count(少量偏差),以避免极大的FindCount耗时。

100万行以上数据表,如若不带条件或者条件没有命中索引,select count 将会极其的慢,在1000万以上甚至查不出来,这是XCode能对100亿表进行分页查询的关键所在

 640?wx_fmt=png

Meta.Count 的初始值来自于数据库元数据索引表,里面有该表主键的总行数,取得该值后如果小于100万再异步select count一次。

10多年前博客园ORM大战的时候,我们常说,等你支持千万级分页的时候再来比,就是钻了select count很慢的这个空子,很多人count出来总数再分页 ^_^

上图4亿数据,查询第10000页,在SQLite单表上,阿里云1C1G服务器。

 

FindCount 分页

在早期版本,不支持RetrieveTotalCount ,只能通过 FindCount 取得满足该条件的总记录数,然后进行分页,至今仍然支持传统方法。

因此可以看到,FindAll 和 FindCount 都是成对出现,参数一摸一样。

并且 FindCount 方法也会带有分页参数,虽然用不到,但.NET2.0时代的 ObjectDataSource 要求两者的参数名称和顺序必须一致。

所有 FindCount 方法,将会得到 select count 查询语句,因此千万级大表需要慎用。

 

PageSplit 分页

内置支持的各种数据库,都有实现普通查询语句转为分页语句的 PageSplit(sql, start, maxNums) 方法。

MySql/SQLite/PostgreSQL 能够很好支持,只需要在 sql 后加上 limit start, maxNums 即可;

Oracle/SqlServer/Access/SqlCe 则要麻烦一次,其中SqlServer最复杂,不同版本的分页方法还不同,早期版本还要求有主键字段;

因此,sql 必须是简单的单表查询语句,PageSplit 才能把任意查询拆开并转换为分页查询。

 

大表分页优化

大表分页查询,开头会很快,越是往后越慢!

XCode采用倒置优化法,对于超过100万行(借助Meta.Count评估)的表,如果查询页超过中线,则从另一个方向查询,然后再把结果倒置回来。

640?wx_fmt=png

 

 

XCode要求数据查询必须考虑分页,没有分页的系统一般死在100万行以内。

 

回到目录

Field扩展

内嵌类_引用的字段是Field,它继承自FieldItem。

Field/FieldItem全部功能:

  • Equal 等于,操作符==

  • NotEqual 不等于,操作符!=

  • 大于操作符>,大于等于>=

  • 小于操作符<,小于等于<=

  • StartsWith 字符串开始,like '{0}%'。(支持索引)

  • EndsWith 字符串结束,like '%{0}'

  • Contains 字符串包含,like '%{0}%'

  • In 集合包含,支持列表集合、字符串子查询和SelectBuilder子查询,集合只有一个元素时转为相等操作

  • NotIn 集合不包含,支持列表集合、字符串子查询和SelectBuilder子查询,集合只有一个元素时转为不相等操作

  • IsNull 是否空

  • NotIsNull 不是空

  • IsNullOrEmpty 字符串空或零长度

  • NotIsNullOrEmpty 字符串非空非零长度

  • IsTrue 是否True或者False/Null,参数决定两组之一

  • IsFalse 是否False或者True/Null,参数决定两组之一

  • Between 时间区间,大于等于开始,小于结束,如果开始结束都只有日期而没有时分秒,则结束加一天,如(2019-04-17,  2019-04-17)查 time>='2019-04-17' and time<2019-04-18'

排序字句/分组聚合

  • Asc,升序

  • Desc,降序。order by name desc

  • GroupBy,分组。group by name

  • As,聚合别名

  • Count,计数

  • Sum,求和

  • Min,最小

  • Max,最大

 

回到目录

查询的本质

查询的本质是五参数版FindAll(where, order, selects, start, maxnums),其它查询方式都由它转化而来!

Entity实体基类封装了各种常用的查询方法:

640?wx_fmt=png

640?wx_fmt=png

640?wx_fmt=png

对于单表查询的XCode来说,五参数版FindAll很容易得到 select [selects] from [table] where [where] order by [order] limit [start], [maxnums] 语句,根据这个理念,FindAll可以支持任意复杂查询!

最终查询语句,由SelectBuilder类承载。

 

回到目录

多表子查询

XCode不支持多表Join关联,这在前面《扩展属性》中提到过。

扩展属性固然可以解决关联多表字段的问题,并且借助缓存性能还不错,但是需要同时在两张表上设置条件的时候,就行不通了。

于是,需要用到高级查询,可以用子查询 来替代,正是前面说到的FieldItem.In扩展。

 

要查询名为“992班”的所有学生,一般这样写:

select * from student s inner join class c on s.classid=c.id where c.name='992班'

XCode从2008年起,就放弃支持多表关联,自然也就不支持这样的写法。

在一般系统里面,班级表数据不多,可以借助实体缓存或者对象缓存:

// Class.FindByName 内部用缓存
var cls = Class.FindByName("992班");
var list = Student.FindAll(Student._.ClassID==cls.ID);
// select * from student where classid=1234

但如果主表从表都是百万级大表,或者从表查询条件比较复杂,缓存就有点难以为继了。

于是有了子查询:

640?wx_fmt=png

调用方法:var list = Student.Search(SexKinds.女, "992班", p);

得到结果:

select * from student where sex=2 and classid in(select id from class where name='992班')

至此,绝大部分多表关联复杂查询语句,可以转化为子查询 !

 

回到目录

系列教程

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抽取,调度计算处理,结果持久化

 


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316204.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软云Azure训练营 | 八城联动,全球盛会

Global Azure Bootcamp是由微软发起、MVP参与组织的全球化学习交流活动。每年会挑选一个特定的时间&#xff0c;在同一天内&#xff0c;全球不同地区将同时开展。2019年全球Azure训练营&#xff08;Global Azure Bootcamp&#xff09;将于2019年4月27日在全球270多个城市同时举…

长沙4月21日开发者大会暨.NET社区成立大会活动纪实

活动总结2019年4月21日是一个斜风细雨、微风和煦的美好日子&#xff0c;由长沙.NET技术社区、腾讯云云加社区、微软Azure云技术社区、中国.NET技术社区、长沙柳枝行动、长沙互联网活动基地&#xff08;唐胡子俱乐部&#xff09;等多家单位共同主办的长沙开发者技术大会暨长沙.N…

SQL Server AlwaysOn 集群 关于主Server IP与Listener IP调换的详细测试

1. 背景SQL Server 搭建AlwaysOn后&#xff0c;我们就希望程序连接时使用虚拟的侦听IP&#xff08;Listener IP&#xff09;&#xff0c;而不再是主Server 的IP。如果我们有采用中间件&#xff0c;则可以在配置中&#xff0c;直接用Listener IP 替换掉 Server IP&#xff0c;可…

在 DotNetCore 3.0 程序中使用通用协议方式启动文件关联应用

问题描述在传统的基于 .NET Framework 的 WPF 程序中&#xff0c;我们可以使用如下代码段启动相关的默认应用&#xff1a;Copy# 启动默认文本编辑器打开 helloworld.txtProcess.Start("helloworld.txt");# 启动默认浏览器打开 https:Process.Start("https://hip…

.NetCoreLinuxDockerPortainer踩坑历险记

最近有一个云服务器和数据库的迁移任务&#xff0c;踩坑爬坑无数次&#xff0c;觉得必须要记录一下。大家瓜子花生准备好&#xff0c;听我慢慢讲故事#手动笑哭#。故事背景公司是做电商业务的&#xff0c;在天猫有几家旗舰店数据量也很大。阿里有一个称为聚石塔的平台&#xff0…

深入源码理解.NET Core中Startup的注册及运行

开发.NET Core应用&#xff0c;直接映入眼帘的就是Startup类和Program类&#xff0c;它们是.NET Core应用程序的起点。通过使用Startup&#xff0c;可以配置化处理所有向应用程序所做的请求的管道&#xff0c;同时也可以减少.NET应用程序对单一服务器的依赖性&#xff0c;使我们…

Python、Java、TypeScript 和 Perl 作者谈语言设计

Python 作者 Guido van Rossum、Java 作者 James Gosling、Turbo Pascal 和 TypeScript 作者 Anders Hejlsberg&#xff0c;以及 Perl 作者 Larry Wall 本月早些时候齐聚一堂&#xff0c;讨论了(YouTube)编程语言设计的过去和未来。Guido van Rossum 说&#xff0c;设计一种语言…

Asp.Net Core Web应用程序—探索

前言作为一个Windows系统下的开发者&#xff0c;我对于Core的使用机会几乎为0&#xff0c;但是考虑到微软的战略规划&#xff0c;我觉得&#xff0c;Core还是有先了解起来的必要。因为&#xff0c;目前微软已经搞出了两个框架了&#xff0c;一个是Net标准(.NetFramework)&#…

智能优化算法应用:基于跳蛛算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于跳蛛算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于跳蛛算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.跳蛛算法4.实验参数设定5.算法结果6.参考文献7.MA…

让你的ASP.NET Core应用程序更安全

对于ASP.NET Core应用程序&#xff0c;除了提供认证和授权机制来保证服务的安全性&#xff0c;还需要考虑下面的一些安全因素&#xff1a;CSRF强制HTTPS安全的HTTP HeadersCSRFASP.NET Core通过AntiForgeryToken来阻止CSRF攻击&#xff0c;一般来说&#xff0c;当用户做表单提交…

.net core 中间件管道底层剖析

.net core 管道&#xff08;Pipeline&#xff09;是什么&#xff1f;由上图可以看出&#xff0c;.net core 管道是请求抵达服务器到响应结果返回的中间的一系列的处理过程&#xff0c;如果我们简化一下成下图来看的话&#xff0c;.net core 的管道其实就是中间件的部分。微软中…

架构为什么要以领域为核心

很久以前, 人们以为地球是太阳系的中心.然后一位聪明人, 哥白尼, 他改变了我们对太阳系的看法. 他认为太阳是太阳系的中心:这是对太阳更好的一个解释, 更简单也更具说服力. 事实上, 以太阳为中心的模型确实是更优雅的.上面这件事也发生在软件开发里. 下面这个就是很多开发者惯用…

201403-5 任务调度

哇&#xff0c;ccf csp认证考试 历年真题解&#xff08;一本书&#xff09;真厉害。 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring>using namespace std;typedef long long LL; typedef pair<int,int> PII; con…

C# - 为引用类型重定义相等性 - 继承相关

派生类这是上面Citizen类的一个子类&#xff1a;下面我重写object.Equals() 方法&#xff1a;大部分逻辑都在base.Equals()方法里了&#xff0c;首先如果父类的Equals()方法返回false&#xff0c;那么下面也就不用做啥了。但是如果父类Equals()认为这两个实例是相等的&#xff…

微软百名员工签名力挺996.ICU

中国程序员上传到 GitHub 的 996.ICU repo 火速在互联网广泛传播时&#xff0c;996 工作制引起了全球的广泛关注&#xff0c;Python 之父直指这是不人道的行为&#xff0c;事情经过不断发酵&#xff0c;中国官方媒体也接连发声表态要警惕「996 工作制」。就在今日&#xff0c;微…

P1174 打砖块

P1174 打砖块 题意&#xff1a; 题解&#xff1a; 参考题解&#xff1a; I_AM_HelloWord danxmz2006 这两个博客结合看&#xff0c;大致就能理解 我们只在N处转移&#xff0c;面对Y类的块无需决策&#xff0c;因为Y类的块可以一直打 不同的打砖块的顺序&#xff0c;决定了我…

包治百病 | 如何将一个.NET Core类库发布到NuGet

点击上方蓝字关注“汪宇杰博客”NuGet是.NET世界的包管理器&#xff0c;有官方的nuget.org&#xff0c;也允许构建公司和私人的服务器。在.NET Core的时代&#xff0c;封装一个NuGet包比以往更容易&#xff0c;我们来看看吧&#xff01;NuGet账号如果你想和微软一起予力众生&am…

如何在ASP.NET Core中使用Azure Service Bus Queue

原文&#xff1a;USING AZURE SERVICE BUS QUEUES WITH ASP.NET CORE SERVICES作者&#xff1a;damienbod[1] 译文&#xff1a;如何在ASP.NET Core中使用Azure Service Bus Queue地址&#xff1a;https://www.cnblogs.com/lwqlun/p/10760227.html作者&#xff1a;Lamond Lu源代…

从B站的代码泄露事件中,我们能学到些什么?

先声明一下&#xff0c;本文不聊ISSUE中的七七八八&#xff0c;也不聊代码是否写的好&#xff0c;更不聊是不是跟蔡徐坤有关之类的吃瓜内容。仅站在技术人的角度&#xff0c;从这次的代码泄露事件&#xff0c;聊聊在代码的安全管理上&#xff0c;通常都需要做哪些事来预防此类事…

[Abp vNext 源码分析] - 3. 依赖注入与拦截器

一、简要说明ABP vNext 框架在使用依赖注入服务的时候&#xff0c;是直接使用的微软提供的 Microsoft.Extensions.DependencyInjection 包。这里与原来的 ABP 框架就不一样了&#xff0c;原来的 ABP 框架还需要抽象出来一个 IIocManager 用来管理整个 IoC 容器&#xff0c;现在…