【问题标题】:Hibernate Query vs Criteria PerformanceHibernate 查询与标准性能
【发布时间】:2010-12-19 13:40:26
【问题描述】:

我最近有一个很奇怪的现象。必须获得一个计数,其中包括具有不同 WHERE 条件的多个表的连接。我首先使用hibernate的标准API实现了查询。它正确地创建了请求的准备好的 SQL 语句,但速度相当慢。然后使用 HQL 重新实现整个查询。这样做相当讨厌,但结果比使用 Criteria API 执行得快得多。有人知道这种行为的原因吗?我假设 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 和 Criteria 查询吗?
  • 查询取决于参数。一个更简单的语句如下所示: select count(*) from R r where r.ISREPLACEDBY = 0 and r.STATUS='OK' and r.A = ?和 r.C in(从 CX cx 中选择不同的 RC,其中 cx.FROMDATE >= ? 和 cx.FROMDATE

标签: performance hibernate


【解决方案1】:

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

【讨论】:

  • 实际上,Criteria 直接转换为 SQL。例如Criterion.toSqlString
  • 这实际上不是真的。它首先生成 HQL,然后对其进行解析。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    Hibernate Criteria 使用反射生成 SQL Statments

    【讨论】:

    • criteria API 的另一个问题是它每次都会生成 HQL(因为每次都可能不同)。这个 HQL 也每次都翻译成 SQL。此翻译尝试通过引发 ClassNotFoundException 的类加载器(例如 generateBla0)加载一些标记。这是一个非常昂贵的操作,因为它会在最后一个类加载器抛出异常之前遍历所有类加载器,并且还涉及类加载器中的一些锁,这会极大地影响性能。忘了提到由于一个错误,整数可能会被插入到 SQL 中而不是参数中。
    【解决方案4】:

    Criteria 理论上应该比 HQL 查询具有更少的开销(命名查询除外,我将介绍它)。这是因为 Criteria 不需要解析任何内容。 HQL 查询使用基于 ANTLR 的解析器进行解析,然后将生成的 AST 转换为 SQL。 但是,使用 HQL/JPAQL,您可以定义命名查询,其中 SQL 在 SessionFactory 启动时生成。理论上,命名查询的开销比 Criteria 少。 因此,就 SQL 生成开销而言,我们有:

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

    在选择 Criteria 和 HQL/JPAQL 时,我会考虑以下几点:

    • 首先,您必须确定是否可以依赖 代码中的 Hibernate 专有 API。 JPA 没有标准。
    • Criteria 非常擅长处理许多可选的搜索参数 例如您可能会在具有多参数的典型网页上找到 '搜索表格'。使用 HQL,开发人员倾向于使用 where 子句 使用 StringBuilder 的表达式(避免这种情况!)。使用标准,您 不需要这样做。
    • HQL/JPAQL 可用于大多数其他事情,因为代码倾向于 更小更易于开发人员理解。
    • 如果你使用真正频繁的查询可以变成命名查询 高质量的。在进行一些分析之后,我更愿意稍后再执行此操作。

    你可以在这里阅读更多信息http://tech.puredanger.com/2009/07/10/hibernate-query-cache/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-13
      • 2012-04-01
      • 2017-08-07
      • 2018-11-16
      • 2013-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多