二级缓存性能

时间:2015-09-24 14:22:50

标签: mysql performance hibernate ehcache

最近我正在研究改进代码的一些可能性,并对其进行了一些更改。我安装了hibernate配置以使用二级缓存,但是这种改进的结果还不够好。我期待我的数据库查询很快就会出现。当我在实现之后做了一些研究之后,时间比我在代码中修改之前的时间要大。即使我启用了缓存查询,我的结果也不会改变。我启用查询缓存后看到的是更糟糕的时间结果。我能看到的另一件事是,如果我的表与另一个表有某种关系,搜索时间会增加很多。

的HibernateUtil

free()

员工

    package com.journaldev.hibernate.util;

import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
public class HibernateUtil {

private static SessionFactory sessionFactory;

private static SessionFactory buildSessionFactory() {
    try {
        // Create the SessionFactory from hibernate.cfg.xml
        Configuration configuration = new Configuration();
        configuration.configure("hibernate.cfg.xml");
        System.out.println("Hibernate Configuration loaded");

        ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build();
        System.out.println("Hibernate serviceRegistry created");

        SessionFactory sessionFactoryLocal = configuration.buildSessionFactory(serviceRegistry);

        return sessionFactoryLocal;
    } catch (Throwable ex) {
        System.err.println("Initial SessionFactory creation failed." + ex);
        ex.printStackTrace();
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory getSessionFactory() {
    if (sessionFactory == null) {
        sessionFactory = buildSessionFactory();
    }
    return sessionFactory;
}}

ADRESS

package com.journaldev.hibernate.model;



    import javax.persistence.Column;
     import javax.persistence.Entity;
     import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "EMPLOYEE")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="employee")
public class Employee {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private long id;

@Column(name = "emp_name")
private String name;

@Column(name = "emp_salary")
private double salary;



public Employee(String name) {
    this.name = name;
}

public Employee() {
}}

员工关系地址

    package com.journaldev.hibernate.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "ADDRESS")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="employee")
public class Address {

    @Id
    @GeneratedValue
    private long id;

    @Column(name = "address_line1")
    private String addressLine1;

    @Column(name = "zipcode")
    private String zipcode;

    @Column(name = "city")
    private String city;


    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getZipcode() {
        return zipcode;
    }

    public void setZipcode(String zipcode) {
        this.zipcode = zipcode;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }


}

Class teste

    package com.journaldev.hibernate.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Cascade;

@Entity
@Table(name = "EMPLOYEE")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="employee")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "emp_id")
    private long id;

    @Column(name = "emp_name")
    private String name;

    @Column(name = "emp_salary")
    private double salary;

    @OneToOne(mappedBy = "employee")
    @Cascade(value = org.hibernate.annotations.CascadeType.ALL)
    private Address address;

    public Employee(String name) {
        this.name = name;
    }

    public Employee() {
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

}

Hibernate.cfg

    package com.journaldev.hibernate.main;

import org.hibernate.Session;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;
import java.util.Date;

public class HibernateEHCacheMain {

    public static void main(String[] args) {
        //insert10000();
        // System.out.println("Temp Dir:" + System.getProperty("java.io.tmpdir"));

        long init1 = new Date().getTime();
        list10000WithCache();
        long end1 = new Date().getTime();
        long result1 = end1 - init1;
        long init2 = new Date().getTime();
        list10000WithCache();
        long end2 = new Date().getTime();
        long result2 = end2 - init2;
        long init3 = new Date().getTime();
        list10000WithCache();
        //list10000WithoutCache();
        long end3 = new Date().getTime();
        long result3 = end3 - init3;
        System.err.println("Result 1 : " + result1 + "\nResult 2 :" + result2 + "\nResult 3 :" + result3);
        System.exit(1);
    }

    private static void insert10000() {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        for (int i = 0; i < 10000; i++) {
            session.save(new Employee(i + ""));
            if (i % 20 == 0) {
                session.flush();
                session.clear();
            }
        }
        session.getTransaction().commit();
        session.close();
    }

    private static void list10000WithoutCache() {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.createQuery("from Employee").list();
        session.getTransaction().commit();
        session.close();
    }

    private static void list10000WithCache() {
        Session session = HibernateUtil.getSessionFactory().openSession();
        session.beginTransaction();
        session.createQuery("from Employee").setCacheable(true).list();
        session.getTransaction().commit();
        session.close();
    }

}

myehcache.xml

    <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration SYSTEM "classpath://org/hibernate/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.password">pass</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost/mydb</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.default_batch_fetch_size">20</property>
        <property name="hibernate.current_session_context_class">thread</property>
        <property name="hibernate.show_sql">true</property>

        <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

        <!-- For singleton factory -->
        <!-- <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property>
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>
        <!-- enable second level cache and query cache -->
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.cache.use_query_cache">true</property>
        <property name="net.sf.ehcache.configurationResourceName">/myehcache.xml</property>

        <mapping class="com.journaldev.hibernate.model.Employee" />
        <mapping class="com.journaldev.hibernate.model.Address" />
    </session-factory>
</hibernate-configuration>

1 个答案:

答案 0 :(得分:0)

查询缓存的工作原理是什么?

查询缓存用于缓存查询结果。打开查询缓存时,将根据组合查询和参数存储查询结果。每次触发查询时,缓存管理器都会检查参数和查询的组合。如果在缓存中找到结果,则返回它们,否则启动数据库事务。

为什么不应使用查询缓存?

正如您所看到的,如果查询具有多个参数,则缓存查询不是一个好主意,因为单个参数可以采用多个值。对于这些组合中的每一种,结果存储在存储器中。这可能导致大量内存使用。

启用查询二级缓存存在很多陷阱。请完成此link

我在配置中没有看到任何问题。您需要在sessionfactory上启用统计信息以查找二级缓存是否正常工作。

  

统计数据统计= sessionFactory.getStatistics();   statistics.setStatisticsEnabled(真);

您可以查看以下值

  

statistics.getEntityFetchCount()

     

statistics.getSecondLevelCacheHitCount()

     

statistics.getSecondLevelCachePutCount()

     

statistics.getSecondLevelCacheMissCount()

使用此post获取有关使用统计信息进行二级缓存的准确说明。