Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >两种1:N分组方法的性能

两种1:N分组方法的性能
EN

Stack Overflow用户
提问于 2018-08-08 21:54:43
回答 2查看 54关注 0票数 1

假设我们在1:N关系中有两个表。现在,假设在java端,您希望将结果数据构建为这样的结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class ParentDto {
    public Long id;
    public String someColumn;
    public List<ChildDto> children = new ArrayList<>();
}

class ChildDto {
    public Long id;
    public Long parentId;
    public String someColumn;
}

从理论上讲,执行单个sql查询是否更快,如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT * 
FROM PARENT_DTO 
    JOIN CHILD_DTO ON PARENT_DTO.ID = CHILD_DTO.PARENT_ID

然后在java端执行像这样的分组操作。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// assume that query is some api to run a query like jdbc that returns theortical type List<Row>
List<ParentDto> results = query(/* query above*/).stream()
    // assume that first value in row is ParentDto::id
    .collect(groupingBy(row -> (Long) row.get(0)))
    // after collect stream type is Map<Long, List<Row>>, whatever row type is from whatever api
    .values()
    .stream()
    // listOfGroupRows is just List<Row>
    .map(listOfGroupedRows -> {
        // assume that ParentDto constructor knows how to fetch values from first row 
        ParentDto rowValue = new ParentDto(listOfGroupedRows.get(0))
        // assume that ChildDto constructor knows how to fetch values from each row
        rowValue.children = listOfGroupedRows.stream()
            .map(row -> new ChildDto(row))
            .collect(toList())
    })

只运行两个单独的查询更快:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SELECT *
FROM PARENT_DTO

SELECT *
FROM CHILD_DTO 

然后在java端执行类似这样的分组操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Map<Long, List<ChildDto>> children = query(/* second query */).stream()
    .map(r -> new ChildDto(r))
    .collect(groupingBy(ChildDto::parentId));

List<ParentDto> results = query(/* first query */).stream()
    .map(r -> {
        ParentDto dto = new ParentDto(r);
        dto.children = children.get(dto.id);
        return dto;
    })
    .collect(toList());

第一种方法只需要对数据库进行一次查询,但卷较高,因为返回的行数为n*m,其中n为父表中的行数,m为子表中的行数。它还会在java端产生2(n * m)的开销(一对组,一组转换每一行)。

第二个方法对数据库产生两个查询,但卷较低,因为返回的行总数为n+m,每一行比原始联接查询的每一行都小。java性能更好,因为它也是n+m (m用于分组子代,n用于处理和初始化父级)。

按照这种逻辑,我总是选择选项二,但我对实际的sql服务器没有太多的实际经验。是否有更有经验的个人会/应该选择备选方案1的情况?另一次向数据库提交的成本会超过这些操作的复杂性差异吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-09 07:00:00

我并不是说这是一个问答风格的帖子,但睡觉后,我意识到我做了一个错误的假设。不同类型的联接具有不同的复杂性。我提到的复杂性(n*m)是交叉连接的内存和计算复杂度,其中两个集合的结果是原始集合的幂集。我最初的联接查询不是交叉连接,而是内部连接。在最坏的情况下,内存复杂度和计算复杂度都是最大值(n,m),但取决于两个表中有多少行不以任何方式与另一个表关联(没有子表的parent_dto不在结果集中)。这也只适用于简单的分组解决方案,因为sql servers使用了许多方法来从根本上改进连接,比如索引操作。

因此,总之,在内部和左联接的实践中,方法1的复杂度较低(max(m,n) vs. m+ n),而且由于索引和其他预calc和缓存方法的存在,它在sql端的解析速度要快得多。唯一的区别是网络开销(冗余规范化数据)略有增加。

票数 0
EN

Stack Overflow用户

发布于 2018-08-08 22:01:59

如果您使用的是像Hibernate这样的ORM框架,这将自动在幕后得到处理。而且,它将使用第一个版本,其中连接发生在数据库上,而不是第二个版本。第一个版本更可取的原因是数据库被设计成非常高效地执行连接之类的任务。Java在执行相同的连接操作时可能效率较低。我甚至看到第二个版本可能更高效的唯一原因是数据往返于数据库的延迟。第二个版本可能涉及传输较少的数据。但是,我认为在Java代码中执行数据库操作的代价将大于此。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51759711

复制
相关文章
为什么这段代码输出的是”Hello World”
Stackoverlfow.com上有一篇有趣的讨论帖: 在这篇帖子里提到了如下的程序: 明明是在程序里使用了java.util.Ramdom()函数产生随机数,为什么每次打出的结果都是Hello w
哲洛不闹
2018/09/14
9910
为什么这段代码输出的是”Hello World”
MSDN官方的ASP.Net异步页面的经典示例代码
示例1.演示异步获取一个网址的内容,处理后显示在OutPut这一Label上 using System; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Net; using System.IO; using System.Text; using System.Text.RegularExpressions; public partial class AsyncPag
菩提树下的杨过
2018/01/24
1K0
为什么这段代码输出的是”Hello World”
Stackoverlfow.com上有一篇有趣的讨论帖: 在这篇帖子里提到了如下的程序: 明明是在程序里使用了java.util.Ramdom()函数产生随机数,为什么每次打出的结果都是Hello w
哲洛不闹
2018/09/19
1K0
为什么这段代码输出的是”Hello World”
代码审查|这段代码,为什么复制文件夹总是“成功”?
最近开始一个人负责整个项目的全栈开发和维护,工作中没了和同事交叉 code review 的环节,所以就打算,如果工作中遇到一些比较典型的代码,包括好味道和坏味道,就拿出来分析下,与大家一起交流,作为另一种形式的「交叉 review」。
mzlogin
2023/10/23
1220
理解项目代码,我做了什么
测试人员如何快速熟悉项目代码,是一个比较头疼的问题,作为测试架构师,有义务去解决这个问题,最近在为团队赋能的时候,做了三件事,来帮助团队成员快速熟悉业务代码,方便后期更好的做测试策略设计。
CKL的思考
2023/02/01
3270
谷歌工程师写的这段代码什么水平?
代码,正在改变世界。正是因为有了代码的存在,才有了阿里巴巴、百度、京东、天猫等的存在。
顶级程序员
2018/07/23
5680
谷歌工程师写的这段代码什么水平?
这段代码很有意思!
作为菜鸟的我,在面试的时候,看到了这阴间代码,心里想着谁无聊写这样的代码呀,屁点用没有,却只能默默的分析题目,但最终还是错了几个,回来之后又好好分析了一下,其实也不是很难,只是在面试的时候看到这样的东西,实在是有点搞心态了!
小丞同学
2021/08/16
5080
JVM优化Java代码时都做了什么?
JVM 在对代码执行的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。运行时优化主要是解释执行和动态编译通用的一些机制,比如说锁机制(如偏斜锁)、内存分配机制(如 TLAB)等。除此之外,还有一些专门用于优化解释执行效率的,比如说模版解释器、内联缓存(inline cache,用于优化虚方法调用的动态绑定)。
本人秃顶程序员
2019/05/28
1.6K0
JVM优化Java代码时都做了什么?
JVM优化Java代码时都做了什么?
JVM 在对代码执行的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。
葆宁
2019/04/18
6290
看完python这段爬虫代码,java流
如果不能正确安装,请检查你的环境变量,至于环境变量配置,在这里不再赘述,相关文章有很多。
py3study
2020/01/22
7030
JVM优化Java代码时都做了什么?
JVM优化Java代码时都做了什么? JVM在对代码执行的优化可分为运行时化和即时编译器优化。运行时优化主要是解析执行和动态编译通用的一些机制,比如说锁机制(如偏向锁)、内存分配机制(如TLAB)。除
葆宁
2019/04/18
4410
new 做了什么?
大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不应该引入另一个更复杂的事物。
小小范
2022/01/20
3790
刚写完这段代码,就被开除了……
显然不是,休眠的逻辑,大家都懂,不需要写注释,你注释写休眠 1 天也没意义啊。。。
Java技术栈
2018/12/11
6770
刚写完这段代码,就被开除了……
中级JAVA:JVM优化Java代码时都做了什么?
JVM 在对代码执行的优化可分为运行时(runtime)优化和即时编译器(JIT)优化。
葆宁
2022/01/06
2060
MSDN 杂志 Windows 8 特刊
Windows 运行时: 使用 Windows 运行时改变应用程序开发的面貌 Windows 运行时是创建 Windows 应用商店应用程序的核心。 了解它如何为创建这些新型应用程序提供强大平台,并附带功能丰富且设计精心一致的开发图面。 Jason Olson Windows 运行时和 CLR: 深入了解 .NET 和 Windows 运行时 综观 CLR 如何使托管开发者与 Windows 运行时交互,公开 Windows 运行时 API,就像它们只是可供 .NET 开发人员使用的另一个托管类库一样。
张善友
2018/01/30
1.1K0
MSDN 杂志 Windows 8 特刊
为什么学了那么多门语言,我还是编不好这段代码
引言:本文节选自朱赟博士在极客时间App开设的“朱赟的技术管理课”,已获授权。更多精彩文章,可以点击文末“阅读原文”免费试读。
Java架构师必看
2021/09/26
3560
链接器做了什么?
摘自《程序员自我修养》 ---- 机器指令的历史 为了更好的理解计算机程序的编译和链接的过程,我们简单地回顾计算机程序开发的历史一定会非常有益。 最原始的设备是就是纸带,即在纸带上打相应的孔。 这个过程我们可以通过图2-6来看到,假设有一种计算机,它的每条指令是一个字节,也就是8位。它的高4位是0001,表示这是一种跳转指令,低4位存放的是跳转目的地的绝对地址。我们可以从图2-6中看到,这个程序的第一条指令就是一条跳转指令,它的目的地址是第5条指令(注意,第5条指令的绝对地址是4).至于0和1怎么映射到
233333
2018/04/13
9900
链接器做了什么?
select语句做了什么?
爱撒谎的男孩
2023/08/25
1250
JS中级测试: 这段代码最终会输出多少?​
可以看到的是 return this 的结果是 WINDOW对象,而不是 obj;
舒克
2019/08/19
1.7K0
点击加载更多

相似问题

这段代码做了什么

70

这段JavaScript代码做了什么?

61

这段perl代码做了什么?

10

这段xkcd代码做了什么?

10

这段javascript代码做了什么?

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文