news 2026/4/16 7:46:57

easy-query暴打efcore(包括其他所有orm),隐式Group看我如何在子查询做到极致的性能天花板

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
easy-query暴打efcore(包括其他所有orm),隐式Group看我如何在子查询做到极致的性能天花板

背景

几个月前其实我已经注意到了一篇帖子《从30秒到30毫秒:EF Core查询性能优化实战全记录》,感兴趣的小伙伴可以自行网上收一下,讲的是如何通过优化提高efcore的性能。

我们对其进行简化,简化部分需求,来讲解本次主题,为什么easy-query这么强,为什么可以这么智能

本次使用的是MYSQL 8本地环境 java8和efcore9

实体关系如下:

用户:每个用户有多篇帖子和多条评论

评论:每条评论属于一个用户并关联一篇帖子

分类:帖子按分类组织

帖子:每个帖子所属一个类目 并且有多个评论

挑战需求:查询过去7天在".NET"分类下评论最多的5位用户,

每位用户返回:

用户ID

用户名

隐式Group

一种更加智能的sql生成,完美的融合了表达式的阅读性和性能,在复杂子查询嵌套和多子查询下合并有种非常高的性能提升,且表达式本身不需要任何变化,是一种非常智能的表达式转变。

先说结论

框架耗时 easy-query普通子查询 efcore子查询 easy-query隐式Group

mysql8 11s 11s 2.7s

创建实体

点击查看实体代码

通过easy-query的code-first生成数据库表,并且生成初始化数据,其中初始化数据为 9个类目,16个用户 发布了15w个帖子并且一个评论100w条记录

点击查看初始化代码

查询数据库

普通子查询

LocalDateTime dateTime = LocalDateTime.now().plusDays(-7);

List<User> list = entityQuery.queryable(User.class)

.where(u -> {

u.comments().any();

})

.orderBy(u -> {

u.comments().where(c -> {

c.createAt().isAfter(dateTime);

c.post().category().name().eq(".NET");

}).count().desc();

})

.limit(5).toList();

最终生成的sql为

SELECT

t.`id`,

t.`username`

FROM

`t_user` t

WHERE

EXISTS (SELECT

1 FROM `t_comment` t1

WHERE

t1.`user_id` = t.`id`

LIMIT

1)

ORDER BY

(SELECT

COUNT(*)

FROM

`t_comment` t2

LEFT JOIN

`t_post` t3

ON t3.`id` = t2.`post_id`

LEFT JOIN

`t_category` t4

ON t4.`id` = t3.`category_id`

WHERE

t2.`user_id` = t.`id`

AND t2.`create_at` > '2025-10-19 22:28:18.469'

AND t4.`name` = '.NET') DESC

LIMIT

5

平均耗时11秒左右

efcore

点击查看实体代码

查询数据库

var dateTime = DateTime.Now.AddDays(-7);

var users = context.Set<User>()

.AsNoTracking()

.Where(u =>u.Comments.Any())

.OrderByDescending(u => u.Comments

.Count(c =>

c.CreatedAt >= dateTime &&

c.Post.Category.Name ==".NET")

)

.Take(5)

.ToList();

生成的sql如下

Executed DbCommand (11,016ms) [Parameters=[@__dateTime_0='2025-10-19T22:32:06.7108910+08:00' (DbType = DateTime), @__p_1='5'], CommandType='Text', CommandTimeout='30']

SELECT `t`.`id`, `t`.`username`

FROM `t_user` AS `t`

WHERE EXISTS (

SELECT 1

FROM `t_comment` AS `t0`

WHERE `t`.`id` = `t0`.`user_id`)

ORDER BY (

SELECT COUNT(*)

FROM `t_comment` AS `t1`

INNER JOIN `t_post` AS `t2` ON `t1`.`post_id` = `t2`.`id`

INNER JOIN `t_category` AS `t3` ON `t2`.`category_id` = `t3`.`id`

WHERE (`t`.`id` = `t1`.`user_id`) AND ((`t1`.`create_at` >= @__dateTime_0) AND (`t3`.`name` = '.NET'))) DESC

LIMIT @__p_1

平均耗时11秒

从结果看两者都是性能相当的,那么为什么本次的主题是暴打efcore呢?

接下来我为大家带来easy-query的究极子查询功能,将子查询转成groupJoin也就是隐式查询的隐式Group可以说.net应该没有ORM做到了这个功能

隐式Group

修改easy-query查询添加一行配置,是的你没听错就一行配置

LocalDateTime dateTime = LocalDateTime.now().plusDays(-7);

List<User> list = entityQuery.queryable(User.class)

.configure(s->s.getBehavior().add(EasyBehaviorEnum.ALL_SUB_QUERY_GROUP_JOIN))

.where(u -> {

u.comments().any();

})

.orderBy(u -> {

u.comments().where(c -> {

c.createAt().isAfter(dateTime);

c.post().category().name().eq(".NET");

}).count().desc();

})

.limit(5).toList();

生成的sql如下

SELECT

t.`id`,

t.`username`

FROM

`t_user` t

LEFT JOIN

(SELECT

t1.`user_id` AS `userId`, (COUNT(*) > 0) AS `__any2__`, COUNT((CASE

WHEN t1.`create_at` > '2025-10-19 22:30:12.833'

AND t4.`name` = '.NET'

THEN 1

ELSE NULL

END)) AS `__count3__` FROM `t_comment` t1

LEFT JOIN

`t_post` t3

ON t3.`id` = t1.`post_id`

LEFT JOIN

`t_category` t4

ON t4.`id` = t3.`category_id`

GROUP BY

t1.`user_id`) t2

ON t2.`userId` = t.`id`

WHERE

IFNULL(t2.`__any2__`, false) = true

ORDER BY

IFNULL(t2.`__count3__`, 0) DESC

LIMIT

5

平均耗时2.7秒 是的你妹看错仅仅只需要一行代码即可让子查询性能提升4-5倍这是什么概念,这就是easy-query带来的最强子查询 隐式Group

鱼和熊掌可以兼得

eq真正的做到了将子查询优化到无敌的存在,可以说目前市面上没有任何一款orm做到了如此智能的sql,性能和可维护性真的可以在easy-query上做到兼得。

具体eq的相关文档点击此处

插曲

我在看《从30秒到30毫秒:EF Core查询性能优化实战全记录》这个文章的时候看到

image

这个表达式,我随机在efcore上试了一下结果性能大跌眼镜要足足22秒也不知道原文是怎么测试的???

var dateTime = DateTime.Now.AddDays(-7);

var users = context.Set<User>()

.AsNoTracking()

.Where(u => u.Comments.Any(c =>

c.CreatedAt >= dateTime &&

c.Post.Category.Name ==".NET"))

.Select(u =>new

{

u.Id,

u.Username,

CommentsCount = u.Comments.Count(c =>

c.CreatedAt >= dateTime &&

c.Post.Category.Name ==".NET")

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 2:48:48

基于PyQt和FFmpeg的开源视频剪辑器OpenShot

penShot的全称是OpenShot Video Editor&#xff0c;它是一款跨平台的开源视频编辑器&#xff0c;适用于Linux、Mac和Windows等系统&#xff0c;且提供了高质量编辑视频和动画的解决方案。编译之后的OpenShot工具环境叫做OpenShot Studios&#xff0c;采用类似剪映的操作界面&am…

作者头像 李华
网站建设 2026/4/10 21:58:35

【计算机毕业设计案例】基于springboot的影院购票管理系统的设计与实现场次管理(同步影片排期、影厅座位、放映技术)、影院选座(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/16 7:42:53

国产数据库技术学习心得:DM数据库实操进阶之路

在信创浪潮推动下&#xff0c;国产数据库技术已成为IT从业者的必备技能。通过《国产数据库技术》课程的系统学习&#xff0c;我以达梦&#xff08;DM&#xff09;数据库为核心&#xff0c;从安装配置到SQL编程完成了全流程实操&#xff0c;深刻体会到国产数据库的高性能与适配性…

作者头像 李华
网站建设 2026/3/31 17:49:02

【课程设计/毕业设计】基于springboot的校园零售管理系统的设计与实现:校园超市、便利店商品【附源码、数据库、万字文档】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/12 10:06:51

Java计算机毕设之基于Java的高校超市管理系统设计与实现基于springboot的校园零售管理系统的设计与实现(完整前后端代码+说明文档+LW,调试定制等)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/4/13 19:00:41

kubernetes中利用LXCFS控制容器资源可见性

背景 Linux 利用 Cgroup 实现了对容器的资源限制&#xff0c;但在容器内部依然缺省挂载了宿主机上的 procfs 的 /proc 目录&#xff0c;其包含如&#xff1a;meminfo、cpuinfo、stat、uptime 等资源信息。一些监控工具如 free、top 或 业务应用还依赖上述文件内容获取资源配置和…

作者头像 李华