1

我基本上是通过运行 JPQL 查询通过 datanucleus 获得一个大小合适的结果集(几千个)。在每一个上,我还想从另一个表中找到引用的数量。数据在 MySQL 数据库中。

例如:

List<Instrument> instruments = em().createQuery("SELECT i FROM Instrument AS i").getResultList();
for(Instrument i : instruments)
{
    Query q = em().createQuery("SELECT COUNT(c) FROM Component AS c WHERE c.instrument.id = :id")
    q.setParameter("id", i.getId());
    long count = (Long) q.getSingleResult();
}

所以,基本上我想要仪器列表以及根据上面的示例连接到仪器的组件列表。

我在很多地方都使用过类似的代码,但性能很差。我知道对于 2000 个仪器,我将触发 2000 个额外的查询来计算组件,这会减慢速度。我确信有更好的模式来获得我想要的相同结果。我怎样才能让事情加速?

4

1 回答 1

1

没错,这不是最优解。但好消息是,所有这些都可以通过一个或最多两个查询来完成。例如,您不必为 each 执行一次计数查询instrument。您可以使用分组并通过一个查询获取所有计数:

List<Instrument> instruments = em().createQuery("SELECT i FROM Instrument AS i").getResultList();

Query q = em().createQuery("SELECT c.instrument.id, COUNT(c) FROM Component AS c GROUP BY c.instrument.id")
List<Object[]> counts = q.getResultList();

for (Object[] elem : counts) {
    // do something 
    // elem[0] is instrument ID
    // elem[1] is count
}

我还没有检查过,但是您也可以通过将第二个查询作为子查询放在第一个查询中来使用一个查询完成所有操作:

SELECT i 
(SELECT COUNT(c) FROM Component AS c WHERE c.instrument.id = i.id)
FROM Instrument AS i

与第一个示例类似,结果列表 elem[0] 将是 anInstrument并且 elem[1] 是计数。它的效率可能会降低,因为无论如何数据库都必须为每个仪器执行子查询,但它仍然比您的代码更快,因为它完全发生在数据库端(每个计数查询都没有到数据库的往返)。

于 2012-10-25T09:45:00.043 回答