我一直在尝试分析JDO查询的性能,(我使用内置的dbcp和mysql)。
我注意到虽然我的查询速度非常快,但如果返回大量记录,则query.execute()可能会慢得多(5ms db查询可能需要40ms执行)。
我已经缩小了对L1Cache的可能原因:
2015-04-17 21:03:46.325 [work-3] DEBUG DataNucleus.Cache - 在第1级缓存中找不到ID为“:758”的对象[缓存大小= 153]
2015-04-17 21:03:46.325 [work-3] DEBUG DataNucleus.Cache - 对象“@ 442b0b9e”(id =“:758”)添加到1级缓存(loadedFlags =“[NYNNNNN]”)
2015-04-17 21:03:46.325 [work-3] DEBUG DataNucleus.Cache - 在第1级缓存中找不到ID为“:759”的对象[缓存大小= 154]
2015-04-17 21:03:46.325 [work-3] DEBUG DataNucleus.Cache - 对象“@ 3f978ede”(id =“:759”)添加到1级缓存(loadedFlags =“[NYNNNNN]”)
2015-04-17 21:03:46.326 [work-3] DEBUG DataNucleus.Cache - 在第1级缓存中找不到ID为“:760”的对象[缓存大小= 155]
2015-04-17 21:03:46.326 [work-3] DEBUG DataNucleus.Cache - 对象“@ 2e0f44f5”(id =“:760”)添加到1级缓存(loadedFlags =“[NYNNNNN]”)
2015-04-17 21:03:46.326 [work-3] DEBUG DataNucleus.Cache - 在第1级缓存中找不到ID为“:761”的对象[缓存大小= 156]
2015-04-17 21:03:46.326 [work-3] DEBUG DataNucleus.Cache - 对象“@ 7db2fe20”(id =“:761”)添加到1级缓存(loadedFlags =“[NYNNNNN]”)
这表明首先检查每条记录(查看它是否在缓存中,然后插入缓存)。有100或1000的记录,这似乎是相当苛刻的表现。
此外,当PersistenceManager关闭时(我正在尝试使用资源),然后销毁此缓存。 ( 所以对于一个简单的select * from Table:
以下是一些示例代码:
try (final PersistenceManagerProvider pmp = getReadPmp()) {
Query q = pmp.get().newQuery(clazz, ":param1.contains(" + field + ")");
@SuppressWarnings("unchecked") List<T> result = (List<T>) q.execute(values);
return result;
}
在此示例中,try尝试使用资源。 close将看起来像这样:
@Override
public void close() {
if (tx != null && tx.isActive()) {
final String stackTrace = new Throwable().getStackTrace()[1].toString(); // element 0 is this method
LOGGER.error("ROLLING BACK UNCOMMITTED TRANSACTION FROM " + stackTrace);
tx.rollback(); // never throws if isActive() is true
}
persistenceManager.close();
}
对于像这样的查询,我只是在select中读取,缓存不提供任何东西,所以它不应该吸收我的性能。 (顺便说一下,我试过禁用l1缓存,这显然不是一个好主意。)
以下是查询中的完整日志集: https://gist.github.com/djerraballi/fafa48a0fa0fea18b31a 这些是调试日志(这可能会显着减慢查询速度,但仍然支持从缓存中删除对象以及插入都是顺序和耗时的理论)。