细节
来自应用程序的HQL查询:
Query q = session.createQuery("from RequestDao r order by r.id desc"); q.setFirstResult(0); q.setMaxResults(50);
查询返回300万条记录,而对于分页,我们仅设置了其中的50条记录,分页页面的运行速度非常慢,因为每次刷新时,我们都调用查询来获取300万条记录,而其中只有50条记录。
我的主要问题是
HQL是始终运行并命中数据库还是运行命中会话或内存以查找数据,如果它每次都运行时命中数据库并获取结果集,那么从性能的角度来看,这是非常合适的,什么是改进的最佳解决方案它?
在hibernate状态下使用HQL是一种方法,我们可以查询数据库并首先仅获取50条记录,然后根据用户要求获取其他记录。这个挑战确实使应用程序陷入瘫痪,那么解决此问题的最佳方法是什么?
日志中生成的HQL查询
from com.delta.dao.RequestDao r order by r.id desc
hibernate生成的查询
select getrequest0_.ID as ID24_, getrequest0_.TIME as START3_24_, getrequest0_.STAT as STATUS24_, getrequest0_.SUM as SUMMARY24_, getrequest0_.OUTNAME as OUTPUT7_24_, getrequest0_.INPNAME as INPUT8_24_, getrequest0_.REQUEST_DATE as requestT9_24_, getrequest0_.PARENT_ID as PARENT10_24_, getrequest0_.INTER_TYPE as INTERPO60_24_, getrequest0_.OPEN_INT as OPEN61_24_, getrequest0_.SOURCE_TYPE as SOURCE62_24_, getrequest0_.TARGET_TYPE as TARGET20_24_, getrequest0_.SOURCE as SOURCE14_24_, getrequest0_.COPY_DATA as COPY16_24_, getrequest0_.CURVE as GENERATE63_24_, getrequest0_.TITLE as TITLE24_, getrequest0_.TIME_ID as TIMESERIES12_24_, getrequest0_.TASK_NAME as TASK51_24_ from REQUEST getrequest0_ where getrequest0_.KIND='csv' order by getrequest0_.ID desc
这是查询的 解释计划 :
| id | select_type | 桌子| 类型 可能的钥匙| 关键 key_len | 参考| 行| 过滤 额外| | 1 | 简单 getrequest0_ | 参考| TR_KIND_ID | TR_KIND_ID | 6 | const | 1703018 | 100.00 | 在哪里使用
附加信息:在50条记录的限制下使用和不使用order by子句的查询运行时间
如果我运行query with order子句,则查询花费 0.0012s 的设置LIMIT 50和without order子句,相同的查询花费 0.0032s的same 和LIMIT 50。
with order
LIMIT 50
without order
另外,我们如何查找是否:
a) Query q = session.createQuery("from RequestDao r order by r.id desc");
b) q.setFirstResult(0); c) q.setMaxResults(50);
在a处,是从数据库获取结果并将其存储在内存中,还是在不存在的地方,这时结果集中有300万个结果,然后在b和c处设置偏移值和限制,因此在页面上只看到50个结果,所以现在剩下300万条记录,在第二次调用此查询时,我们再次访问数据库并获得300万条记录并将其存储在内存中,然后在c处再次设置50条记录并继续执行上。
这个问题对我来说尚不明确,因此,如果有人可以提供清晰详细的解释,说明它的工作方式以及解决该问题的最佳方法,将不胜感激。
更新资料
事实证明,问题与页面上的记录显示无关,但是我在该页面上进行了过滤,并且在每个请求上都再次从数据库中获取所有下拉值,并且其中存在一些时髦的事情导致页面加载时间增加。
我正在对数据库进行多个嵌套的hibernate查询,并返回结果,什么是解决此问题的最佳解决方案?
您的查询告诉数据库对满足WHERE子句的所有记录进行排序。在返回前50名之前,它可能会排序数百万条记录。
编辑1/26:现在已经弄清了具体问题,我将尝试更具体地回答。
每次执行这样的查询时,Hibernate都会进入数据库。甚至还会将会话中的所有新/更新数据刷新到磁盘。如果这是您的情况,则此行为可能会导致速度变慢。
在大多数情况下,使用Hibernate Query API的效果通常都很好,并且与各种数据库平台兼容。如果您真的很想降低数据访问层的性能,可以编写自己的本机SQL查询来选择前50个结果。但是,一旦这样做,您几乎肯定会失去数据库独立性。因此,请评估您的成本与收益。
您的查询运行时间似乎在毫秒级范围内。这通常与将数据存储在磁盘上的关系数据库一样好。因此,您可能需要评估您是否确实存在性能问题。
编辑1/27:好的。看起来好像页面的总体设计中存在问题。我使用AJAX已有大约7年了,因此在浏览表格的页面时,我通常不必等待筛选UI控件重绘。我想,切换应用程序UI框架不是您的选择。您必须找出如何优化下拉列表等数据的加载。此数据是否经常更改?您可以将其缓存在应用程序中的某个位置吗?如果您必须每次都加载它们,是否可以只获取显示字符串而不是整个对象而摆脱困境?