Hibernate 性能调优技巧

3

我正在开发一个小型应用程序,它只包含一个表。

我正在使用的技术如下: NetBeans 8.1 Java 8 Hibernate 4.3.x Informix Primefaces 5

我花了一些时间研究如何使用Hibernate连接Informix,但最终成功了,并且应用程序能够正确地显示所请求的数据列表。

然而,Hibernate的性能问题很严重,特别是考虑到该表只包含36000条记录。

每次页面更改都需要大约6或7秒钟。

我已经在Hibernate的官方文档中进行了研究,但没有找到具体的例子来提高性能。

以下是应用程序代码:

hibernate.cfg.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
   <property name="hibernate.dialect">org.hibernate.dialect.InformixDialect</property>
   <property name="hibernate.connection.driver_class">com.informix.jdbc.IfxDriver</property>
   <property name="hibernate.connection.url">jdbc:informix-sqli://127.0.0.1:1526/chicho:INFORMIXSERVER=ol_chicho</property>
   <!--<property name="hibernate.connection.datasource">jdbc/votacion</property>-->
   <property name="hibernate.connection.username">informix</property>
   <property name="hibernate.connection.password">informix</property>
   <property name="hibernate.connection.autocommit">true</property>
   <property name="hibernate.current_session_context_class">thread</property>
   <property name="hibernate.default_schema">informix</property>
   <property name="hibernate.show_sql">true</property>
   <property name="hibernate.hbm2ddl.auto">validate</property>
   <property name="hibernate.cache.use_second_level_cache">true</property>
   <mapping resource="pojos/Xxpuedenvotar1.hbm.xml"/>
 </session-factory>

普通Java对象(POJO):

package pojos;
// Generated 23/08/2016 22:07:42 by Hibernate Tools 4.3.1



/**
 * Xxpuedenvotar1 generated by hbm2java
 */
public class Xxpuedenvotar1  implements java.io.Serializable {


 private Integer nroaccionista;
 private Short estado;
 private Integer idcliente;
 private String razonSocial;
 private Short idlocalidad;
 private Short zona;
 private String calle;
 private String puerta;
 private String localidad;

public Xxpuedenvotar1() {
}


public Xxpuedenvotar1(Integer nroaccionista) {
    this.nroaccionista = nroaccionista;
}
public Xxpuedenvotar1(Integer nroaccionista, Short estado, Integer idcliente, String razonSocial, Short idlocalidad, Short zona, String calle, String puerta, String localidad) {
   this.nroaccionista = nroaccionista;
   this.estado = estado;
   this.idcliente = idcliente;
   this.razonSocial = razonSocial;
   this.idlocalidad = idlocalidad;
   this.zona = zona;
   this.calle = calle;
   this.puerta = puerta;
   this.localidad = localidad;
}

public Integer getNroaccionista() {
    return this.nroaccionista;
}

public void setNroaccionista(Integer nroaccionista) {
    this.nroaccionista = nroaccionista;
}
public Short getEstado() {
    return this.estado;
}

public void setEstado(Short estado) {
    this.estado = estado;
}
public Integer getIdcliente() {
    return this.idcliente;
}

public void setIdcliente(Integer idcliente) {
    this.idcliente = idcliente;
}
public String getRazonSocial() {
    return this.razonSocial;
}

public void setRazonSocial(String razonSocial) {
    this.razonSocial = razonSocial;
}
public Short getIdlocalidad() {
    return this.idlocalidad;
}

public void setIdlocalidad(Short idlocalidad) {
    this.idlocalidad = idlocalidad;
}
public Short getZona() {
    return this.zona;
}

public void setZona(Short zona) {
    this.zona = zona;
}
public String getCalle() {
    return this.calle;
}

public void setCalle(String calle) {
    this.calle = calle;
}
public String getPuerta() {
    return this.puerta;
}

public void setPuerta(String puerta) {
    this.puerta = puerta;
}
public String getLocalidad() {
    return this.localidad;
}

public void setLocalidad(String localidad) {
    this.localidad = localidad;
}
}

DAO:

package Dao;

import Interfaces.InterfazSocios;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import pojos.Xxpuedenvotar1;

/**
 *
 * @author Gustavo
*/
public class DaoSocios implements InterfazSocios {

private List<Xxpuedenvotar1> listaSocios;

@Override
public List<Xxpuedenvotar1> verTodos(Session sesion) throws Exception {
    String hql = "FROM Xxpuedenvotar1 ORDER BY NroAccionista";
    //Query consulta = sesion.createQuery(hql).setCacheable(true);
    this.listaSocios = sesion.createCriteria(Xxpuedenvotar1.class).list();
    //this.listaSocios = consulta.list();
    return this.listaSocios;
}

}

我认为这些文件足以进行分析,因为该应用程序运行良好,除了它的缓慢。

提前感谢您的关注。


我看到你在Hibernate配置中启用了SQL日志记录。当你运行生成的查询语句时会发生什么?你还是觉得很慢吗?你有更好的查询语句可以替代HQL吗? - Ramachandran.A.G
2
如果按排序字段未建立索引,这可能会变得非常缓慢。 - holtc
闻起来像是索引问题。请发出表的数据定义语句(DDL)。 - chrylis -cautiouslyoptimistic-
@Ramachandran,如果我在Hibernate之外运行SQL查询,结果会立即显示,速度非常快。我没有更好的查询,因为它非常基本(要求基于所有记录)。这就是让我感到惊讶的地方,因为如果我使用未使用Primefaces的JSF模板进行操作,分页效果非常出色。 - Gustavo Echenique
2个回答

1
首先,有很多方法可以加速Hibernate。请查看这些高性能Hibernate技巧或者这个高性能Hibernate视频演示

现在回到您的问题上。您正在使用DriverManagerConnectionProvider,它只提供了一个基本的连接池解决方案。最好使用HikariCP,因为它是最快的,并且还可以通过hibernate-hikaricp Maven依赖项获取。

关于您的陈述:

“问题出现在Hibernate的性能上,非常糟糕,特别是考虑到表格只包含36000条记录。”

为什么要一次性检索36k条记录呢?

您不能将它们显示到UI中吗?这就是我们拥有数据分页的原因。

即使对于批处理器,您最好将整个工作量分成多个较小的数据集,以避免长时间运行的事务,甚至将负载分担在多个工作线程之间。


0

根据配置和修改配置属性的可用性,可以尝试其中任何一个或所有。

  • hibernate.show_sql:在完成查询构建分析后将其标记为false。记录此项需要时间。
  • 如果使用连接池,则可以更改连接池大小配置。
  <property name="hibernate.c3p0.min_size">5</property>
  <property name="hibernate.c3p0.max_size">20</property>

这有助于从池中快速获取连接。避免了获取连接所需的时间。

  • 如果您有大量数据,请在JPA类中使用@OrderBy标记相应的列。

  • Hibernate搜索提供@SortableField来注释字段,这在内部进行索引并帮助检索排序结果。

[编辑]

如果Integer nroaccionista是主键,默认情况下会进行索引。请在JPA类中使用@Id标记该列,并且生成的DDL创建语句将默认创建索引。索引列有助于更好地搜索和排序结果。

希望对您有所帮助。


我尝试使用您在帖子中提供的参数来创建一个C3P0连接池,同时也通过JNDI连接到GlassFish,但结果是一样的。NroAccionista列是主键,因此已经建立了索引。我无法理解问题出在哪里。 - Gustavo Echenique
如果服务器是本地主机,打开JVisualVM并连接到本地服务器,分析线程转储以确定调用堆栈占用更多的内存和处理时间的位置。这可以让您完全了解如何减少时间和空间复杂度。 - Vinay Veluri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接