Bezdepbonusu7Программирование: статьи и ответы

Вопрос

SpringData и Querydsl генерируют неоптимальный запрос

Автор вопроса: PalladiumОтветов: 1

Я использую JPA (Hibernate v4.1.7), Spring Data (v1.4.1) и Query DSL (v3.2.3) для построения моего уровня DAO в базе данных Postgres.

Но сгенерированный SQL для запросов не оптимален для фильтрации по отношению @ElementCollection (аналогичная проблема существует с отношением @OneToMany)

У меня есть сущность:

@Entity
@Table(name = "doc_documents")
public class Document {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "doc_document_titles",
        joinColumns =
        @JoinColumn(name = "document_id"))
    @Column(name = "title")
    private List<String> titles = new ArrayList<>();
....
)

И интерфейс репозитория:

public interface DocumentRepo
        extends JpaRepository <Document, Long>,
                QueryDslPredicateExecutor<Document> {
}

Когда я выполняю свой запрос:

Predicate crit = qDoc.titles.any().eq("x");
docRepo.findAll(crit);

Этот SQL выполняется:

select
    document0_.id as id10_
from
    doc_documents document0_
where
    exists (
        select
            1
        from
            doc_documents document1_
        inner join
            doc_titles title2_
                on document1_.id= title2_.document_id
        where
            document1_.id=document0_.id
            and locthesaur2_.title = ?
    )

Но я думаю, что оптимальный SQL для этого запроса должен быть без дополнительного внутреннего соединения:

select
    document0_.id as id10_
from
    doc_documents document0_
where
    exists (
        select
            1
        from
            doc_titles title2_
        where
            title2_.document_id=document0_.id
            and title2.title= ?
    )

Дополнительное внутреннее соединение серьезно портит производительность. Можно ли указать QueryDSL для генерации другого запроса, или, может быть, я просто делаю что-то не так?

Проблема производительности жизненно важна для моего приложения, поэтому без этой оптимизации я не могу использовать QueryDSL для запросов к базе данных (у меня гораздо более сложный домен, чем я показал здесь).

  • Какую версию Querydsl вы используете? Timo Westkämper 03.12.2013
  • Версия QueryDsl - 3.2.3. Palladium 03.12.2013

spring-dataquerydsl

Ответы

Ответ 1 · Timo Westkämper

Предикат внутренне переводится во что-то подобное на уровне JPQL.

exists (select 1
        from Document doc2
        inner join doc2.titles as doc2_titles
        where doc2 = doc and doc2_titles = ?)

Невозможно использовать заголовки непосредственно в части from, так как это не сущность. Дайте мне знать, если вы найдете лучший способ выразить это в JPQL.

Если есть аналогичная проблема для OneToMany, создайте для этого тикет.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы