英文:
How to Improve performance of iteration loops
问题
以下是翻译好的内容:
我有一个查找父节点的所有子节点(叶子节点)的 Java 方法。它能正常工作,但存在性能问题。在子节点数量变多时,问题变得突出。下面是这个方法:
private void getChildren(String orgId, List<String> children, List<String> organs, int j) {
Query query = entityManager.createNativeQuery("select c.organization_id from organization c where c.parent_org_id=" + orgId);
if (query.getResultList().size() > 0)
organs.addAll((List<String>) query.getResultList());
else
children.add(orgId);
for (int i = j + 1; i < organs.size(); i++) {
j = i;
query = entityManager.createNativeQuery("select c.organization_id from organization c where c.parent_org_id=" + String.valueOf(organs.get(i)));
if (query.getResultList().size() > 0)
organs.addAll((List<String>) query.getResultList());
else
children.add(String.valueOf(organs.get(i)));
}
}
我调用这个方法的方式如下:
getChildren("68", new ArrayList<>(), new ArrayList<>(), -1);
我使用的是 Oracle 数据库,如果通过 Oracle 查询可以更好地实现这一点,请告诉我。顺便说一下,我的 Spring 版本不支持流(streams)。
英文:
I have a java method which finds all children (leaves) of a parent. It works ok.but there is performance issue. How can i make it work faster? When the children gets large it becomes problematic. Here is the method:
Private void getChildren(String orgId, List<String> children, List<String> organs, int j){
Query query= entityManager.createNativeQuery("select c.organization_id from organization c where c.parent_org_id="+orgId);
if(query.getResultList().size()>0)
organs.addAll((List<String>) query.getResultList());
else
children.add(orgId);
for(int i=j+1; i<organs.size();i++){
j=i;
query=entityManager.createNativeQuery("select c.organization_id from organization c where c.parent_org_id="+String.valueOf(organs.get(i)));
if(query.getResultList().size()>0)
organs.addAll((List<String>) query.getResultList());
else
children.add(String.valueOf(organs.get(i)));
}
}
I call this method like
getChildren("68",new ArrayList<>(),new ArrayList<>(),-1)
I have oracle as database so if it is better to acheive this via oracle query please note me.
By the way my spring version doesn't support streams!
答案1
得分: 3
你基本上有一个1+N的选择问题(为集合中的每个id发出单独的查询)。不要这样做,而是使用IN
子句发出单个查询!
另一件你不应该做的事情是在查询创建时使用连接操作,绝对不要这样做!你应该做的是只返回结果,并使用带有IN
子句的查询。
String query = "select c.organization_id from organization c where c.parent_org_id IN (:ids)";
return em.createNativeQuery(query).setParameter("ids", organs);
或者更好的做法是完全使用单个查询。你可以使用自连接来实现这个)
String query = "SELECT c1.organization_id " +
"FROM organization c1 LEFT OUTER JOIN organization c2 " +
"ON c1.parent_org_id=c2.organization_id " +
"WHERE c2.parent_org_id=?";
return em.createNativeQuery(query, String.class).setParameter(1, orgId).getResultList();
根据你的解决方案,我强烈建议学习SQL和JPA。
英文:
You basically have a 1+N select problem (issue a single query for each id in your collection). Don't do this, instead use the IN
clause and issue a single query!.
Another thing you shouldn't be doing is use concat for your query creation, never do this! What you should do is just return the result and use a query with an IN
clause.
String query = "select c.organization_id from organization c where c.parent_org_id IN (:ids))
return em.createNativeQuery(query).setParameters("ids", organs);
or even better use a single query altogether. You can use a self join for that)
String query = "SELECT c1.organization_id " +
"FROM organization c1 LEFT OUTER JOIN organization c2 " +
"ON c1.parent_org_id=c2.organization_id " +
"WHERE c2.parent_org_id=?";
return em.createNativeQuery(query, String.class).setParameter(1, orgId).getResultList();
Judging from your solution I would strongly recommend studying SQL and JPA.
答案2
得分: 1
尝试在大查询中使用
从组织中选择 c.organization_id ,其中 (
从组织中选择 c.organization_id 作为 sub1 ,其中 c.parent_org_id="+orgId +" ) 作为 x_ ,
其中 organization.parent_org_id = x_.sub1
之所以慢的原因是,您为每个子项查询了数据库。这是非常低效的,我认为甚至数据库的负载也会较小。
英文:
Try it in a big query
select c.organization_id from organization, (
select c.organization_id as sub1 from organization c where c.parent_org_id="+orgId +") as x_ where organization.parent_org_id = x_.sub1
The reason why it is slow, is that you query the database for every child. This is very inefficient, I assume even the load on the database will be smaller.
答案3
得分: 0
Deinum提供的答案仅获取直接子项。而我的Java方法会返回包括嵌套子项在内的所有子项。
我已找到了一个比我的Java方法更优化的查询方法。它使用临时表:
with temp_tbl (id,parent_id) as
(
select organization_id,parent_org_id from organization where parent_org_id =?
union all
select c.organization_id ,c.parent_org_id from organization c join temp_tbl t on t.id=c.parent_org_id and t.parent_id !=t.id
)
Select to_char(g.id) from temp_tbl g
最后我返回to_char(g.id)
将其转换为字符串,而不是大十进制数。因为em.createNativeQuery(query, String.class)
没有将其转换为字符串,对我抛出了错误。所以只需使用em.createNativeQuery(query)
。
英文:
Answer provided by Deinum only gets the direct children. Whereas my java method returns all children including nested ones.
I have found a query for that which is much more optimized than my java method. It uses temporary tables:
with temp_tbl (id,parent_id) as
(
select organization_id,parent_org_id from organization where parent_org_id =?
union all
select c.organization_id ,c.parent_org_id from organization c join temp_tbl t on t.id=c.parent_org_id and t.parent_id !=t.id
)
Select to_char(g.id) from temp_tbl g
At the end i return to_char(g.id)
to make it a string instead of big decimal. Because em.createNativeQuery(query, String.class)
didn't turn it to string and threw error for me.
So just use em.createNativeQuery(query)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论