Сортировать против OrderBy - влияние на производительность - PullRequest
0 голосов
/ 27 января 2019

В дополнение к jpa's @OrderBy, который упорядочивает элементы на уровне SQL, hibernate предоставляет @SortComparator и @SortNatural, которые являются элементами сортировки после загрузки из базы данных.

  1. Какой из них лучше, когда речь идет о производительности?
  2. Если @OrderBy лучше, зачем кому-то использовать другой вариант, поскольку он даже не является стандартом jpa?

Ответы [ 2 ]

0 голосов
/ 02 апреля 2019

Во-первых, @SortComparator и @SortNatural не сортируют элементы после загрузки их из БД, но сортируют их во время их вставки.Таким образом, элементы сортируются в памяти.

При использовании @OrderBy (CULOMN_NAME ASC) Hibernate сортирует элементы коллекции, когда элементы загружаются из БД путем выполнения оператора Select с помощью ORDER BY.

Я измерил производительность для @SortNatural и @OrderBy (clause = "random_string ASC". Хранение и загрузка 200 тыс. Случайных строк с длиной восьмых символов. (Используемый код ниже.)

Результаты:

Сохранение данных с помощью @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;
}
}

main

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.Answer of Как создать случайную буквенно-цифровую строку?

0 голосов
/ 27 января 2019

ссылка: https://thoughts -on-java.org / ordering-vs-sorting-hibernate-use /

Используйте OrderBy, если функция часто вызывается.

Используйте Сортировку, если вы хотите загрузить все данные в память и управляете ими вручную.

...