Performance Hibernate查询与条件性能

Performance Hibernate查询与条件性能,performance,hibernate,Performance,Hibernate,我最近有一个相当奇怪的现象。必须获得包含多个具有不同WHERE条件的表上的联接的计数。我首先使用hibernate的CriteriaAPI实现了查询。它正确地创建了请求的准备好的SQL语句,但速度相当慢。然后使用HQL重新实现整个查询。这样做相当糟糕,但结果比使用CriteriaAPI执行的速度快得多。有人知道这种行为的原因吗?我假设Criteria和HQL框架使用相同的代码库将其转换为SQL 以下是查询: select count(*) from R r where r.ISREPLACEDB

我最近有一个相当奇怪的现象。必须获得包含多个具有不同WHERE条件的表上的联接的计数。我首先使用hibernate的CriteriaAPI实现了查询。它正确地创建了请求的准备好的SQL语句,但速度相当慢。然后使用HQL重新实现整个查询。这样做相当糟糕,但结果比使用CriteriaAPI执行的速度快得多。有人知道这种行为的原因吗?我假设Criteria和HQL框架使用相同的代码库将其转换为SQL

以下是查询:

select count(*) from R r where r.ISREPLACEDBY = 0 
and r.STATUS='OK' and r.A = ? 
and r.C in 
   (select distinct RC from CX cx where cx.FROMDATE >= ? and cx.FROMDATE <=?)

我通常认为HQL是非常接近最优的,因为它几乎是直接的SQL,只有一些替换。我假设从HQL到SQL的转换只是替换;CriteriaAPI可能会生成HQL,然后进行转换。一般来说,HQL是你最好的选择。

我想我终于找到了原因。似乎CriteriaAPI在每次执行准备好的语句时都会创建新的变量名。在我们的例子中,DB2在每次执行语句时计算一个新的查询执行计划。另一方面,HQL使用相同的变量名,允许数据库重新使用查询执行计划。

Hibernate条件使用反射生成SQL语句

理论上,条件的开销应该比HQL查询小,但命名查询除外,我将对此进行介绍。这是因为条件不需要解析任何东西。 HQL查询使用基于ANTLR的解析器进行解析,然后将生成的AST转换为SQL。 但是,使用HQL/JPAQL可以定义命名查询,其中SQL是在SessionFactory启动时生成的。理论上,命名查询的开销比标准小。 因此,就SQL生成开销而言,我们有:

命名HQL/JPAQL查询-SQL生成只发生一次。 条件-在生成之前无需解析。 非命名HQL/JPAQL查询-解析,然后生成。 也就是说,在我看来,根据解析和SQL生成的开销选择查询技术可能是一个错误。 与使用真实数据在真实数据库服务器上执行真实查询相比,此开销通常非常小。如果在评测应用程序时确实出现了这种开销,那么您可能应该切换到命名查询。 这是我在判断标准和HQL/JPAQL:

时所考虑的问题。 首先,你必须决定你是否可以依赖 在代码中使用Hibernate专有API。JPA没有标准。 Criteria非常擅长处理许多可选的搜索参数 例如,您可以在具有多个参数的典型网页上找到 “搜索表单”。使用HQL,开发人员倾向于附加where子句 使用StringBuilder的表达式可避免此问题!。有了标准,你 我不需要那样做。 HQL/JPAQL可以用于大多数其他事情,因为代码倾向于 使其更小,更易于开发人员理解。 如果使用 HQL。我更喜欢稍后再做,在一些分析之后。
您可以在此处阅读一些其他信息

您可以显示HQL和条件查询吗?查询取决于参数。其中一个较简单的语句如下所示:从R中选择count*,其中R.ISREPLACEDBY=0,R.STATUS='OK'和R.A=?和r.C中选择与CX不同的RC,其中CX.FROMDATE>=?实际上,条件直接转换为SQL。e、 这实际上是不正确的。CriteriaAPI的另一个问题是,它每次都会生成HQL,因为每次都可能不同。此HQL每次也会转换为SQL。此转换尝试通过类加载器加载一些标记,例如generatedBla0,它引发ClassNotFoundException。这是一个非常昂贵的操作,因为在最后一个类加载器抛出异常之前,它会遍历所有类加载器,并且还涉及类加载器中的一些锁,这会极大地影响性能。忘了提到,由于一个bug,整数可能被插入SQL而不是参数。