我们的开发团队最近担心标准和HQL太慢。我运行了一些基准来了解缓慢来自何处。
我分别运行了1001次以下查询。第一次运行查询时,实体不会被会话缓存,但每次都会缓存实体。
Entity e = (Entity) session.get(Entity.class, new EntityID("Composite key value 1", "Composite key value 2"));
First call:
80.505875
Average of next 1000 calls:
0.045958 ms
Entity e = (Entity) session.createCriteria(Entity.class)
.add(Restrictions.eq("id", new EntityID("Composite key value 1", "Composite key value 2")))
.uniqueResult();
First call:
91.489098 ms
Average of next 1000 calls:
0.847434 ms
作为旁注,HQL中的相同查询第一次花费的时间更长,但在所有后续调用中统计上相同。
我已经读过,与数据库查询相比,HQL和HQL到SQL转换的标准需要花费很少的时间。根据我的测试,这些翻译似乎比会议获得的时间长了 18.4 。
0.847434 / 0.045958 = 18.439314
假设一些实现细节,我希望查询的转换需要0.801476 ms。这意味着只要会话获得,转换步骤就会花费 17.4 次。使用JDBC,我们可以在0.025368 ms内运行这些查询。这是一个以前使用ODBC的转换项目,所以我们正在寻找与之前相当的速度。但是,即使使用缓存,似乎我们也无法接近可比较的速度。
(0.847434 - 0.045958) / 0.045958 = 17.439314
我期望通过使用缓存来避免与数据库交谈,我们将在后续调用中达到与JDBC相当的速度。标准转换是否正常运行一毫秒的大部分时间?人们如何使用标准达到与JDBC相当的速度?
编辑:我的帖子包含一个重大错误,它出现了相同的代码,产生了两个不同的统计数据。现在已经修复了。
答案 0 :(得分:0)
我分别运行了1001次以下查询。第一次运行查询时,实体不会被会话缓存,但每次会话都被缓存。
你的假设是错误的。使用Criteria API时,条件查询不会缓存在持久性上下文中。即使您使用id属性,也会执行SQL查询。而在使用get
方法时,该对象确实在第一级缓存(持久性上下文)中维护。
您可以通过启用show_sql=true
来验证它。对于第一个用例,您将看到单个查询打印输出。对于条件,您将看到1000个查询。
第一次预热调用显着减慢的原因是因为必须从pool / created获取连接,可以缓存语句等。
如果这样说,将setCacheable(true)
添加到条件中,您会看到平均时间下降到接近调用get
的水平。