排序与订购-对性能的影响

时间:2019-01-27 05:59:00

标签: performance hibernate sorting jpa sql-order-by

除了jpa的@OrderBy(在SQL级别上对元素进行排序)之外,hibernate还提供了@SortComparator@SortNatural,它们是从数据库加载后对元素进行排序的。

  1. 在性能方面哪个更好?
  2. 如果@OrderBy更好,为什么还会有人使用另一个选项,因为它甚至不是jpa标准?

2 个答案:

答案 0 :(得分:1)

首先,@SortComparator和@SortNatural在从数据库中加载元素后不对元素进行排序,而是在插入期间对其进行排序。因此,元素在内存中排序。

使用@OrderBy(CULOMN_NAME ASC)时,当通过使用ORDER BY执行Select-Statement从数据库加载元素时,Hibernate会对集合的元素进行排序。

我测量了@SortNatural和@OrderBy(clause =“ random_string ASC”的性能。 存储和加载200k个长度为8个字符的随机字符串。 (使用的代码在下面。)

结果是:

使用@SortNatural存储数据:

  1. 472秒
  2. 424秒

使用@SortNatural加载数据:

  1. 2.6秒
  2. 1,7秒
  3. 1,7秒
  4. 3.0秒
  5. 1,2秒

使用@OrderBy存储数据

  1. 431秒
  2. 413秒

使用@OrderBy加载数据

  1. 3.3秒
  2. 3.3秒
  3. 3.0秒
  4. 3.5秒
  5. 4.8秒

hibernate.cfg.xml

<!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="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://localhost:3306/hibernateTest</property>
        <property name="connection.username">root</property>
        <property name="connection.password"></property>

        <property name="conection.pool_size">1</property>

        <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>

        <property name="show_sql">true</property>

        <property name="current_session_context_class">thread</property>
        <property name="hibernate.hbm2ddl.auto">create</property>
    </session-factory>
</hibernate-configuration>

ClassWithStringCollection

@Entity
@Table(name="class_with_string_collection")
public class ClassWithStringColloction{
@Id
@Column(name="id")
private int id;

@ElementCollection
@CollectionTable(name="random_strings")
@Column(name="random_string")
//@SortNatural
@OrderBy(clause = "random_string ASC")
protected SortedSet<String> randomStrings = new TreeSet<String>();

public ClassWithStringColloction() {

}

public ClassWithStringColloction(SortedSet<String> modules) {
    this.randomStrings = modules;
}

public int getId() {
    return id;
}

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

public SortedSet<String> getRandomStrings() {
    return randomStrings;
}

public void setRandomStrings(SortedSet<String> randomStrings) {
    this.randomStrings = randomStrings;
}
}

主要

public class main {

    public static void main(String[] args) {

        SessionFactory factory = new Configuration()
                            .configure("hibernate.cfg.xml")
                            .addAnnotatedClass(ClassWithStringColloction.class)
                            .addAnnotatedClass(RandomString.class)
                            .buildSessionFactory();
        Session session = factory.getCurrentSession();

        try {

            long timeBefore;
            long timeAfter;
            long elapsed;

            SortedSet<String> randomStrings = new TreeSet();
            ClassWithStringColloction classWithSC = new ClassWithStringColloction(new TreeSet());

            //performance measurement propagating data to DB

            RandomStringGenerator randStringGen = new RandomStringGenerator(10);
            String randomString = "";

            session.beginTransaction();
            session.persist(classWithSC);
            classWithSC = session.find(ClassWithStringColloction.class, 0);
            randomStrings = classWithSC.getRandomStrings();

            timeBefore = System.currentTimeMillis();
            for (int i = 0; i < 200000; i++) {

                randomString = randStringGen.nextString();
                randomStrings.add(randomString);
                session.update(classWithSC);
                if (i % 100 == 0) {
                session.flush();
                session.clear();
                }
            }

            session.getTransaction().commit();

            timeAfter = System.currentTimeMillis();
            elapsed = timeAfter - timeBefore;
            System.out.println("Time for storing 200000 String:" + elapsed + " ms");


            //Performance measurement for loading stored data.
            session = factory.getCurrentSession();

            session.beginTransaction();
            timeBefore = System.currentTimeMillis();
            classWithSC = session.get(ClassWithStringColloction.class, 0);
            randomStrings = classWithSC.getRandomStrings();
            System.out.println(randomStrings.first());
            session.getTransaction().commit();

            timeAfter = System.currentTimeMillis();
            elapsed = timeAfter - timeBefore;
            System.out.println("Time for loading 200000 Strings:" + elapsed + " ms");

            System.out.println("Done");

        } catch (Exception e) {
            e.printStackTrace();
        }
        session.close();

    }

}

RandomStringGenerator 1,答案 How to generate a random alpha-numeric string?

答案 1 :(得分:0)

参考:https://thoughts-on-java.org/ordering-vs-sorting-hibernate-use/

如果函数经常调用,请使用OrderBy。

如果要将所有数据加载到内存中并手动进行管理,请使用“排序”。