Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JPAQuery executes Projections 50% faster than QuerydslPredicateExecutor #3160

Closed
membersound opened this issue Sep 14, 2023 · 1 comment
Closed
Assignees
Labels
status: superseded An issue that has been superseded by another

Comments

@membersound
Copy link

membersound commented Sep 14, 2023

I detected a strange performance issue that I'd like to share.
My goal is to find all rows based on a querydsl Predicate, and return them as a stream of Projections.

Now I created this function once in a Repository interface, and once manually using JPAQuery.
Surprisingly. the JPAQuery only takes 50% of the time, even though the resulting query should be equal.

public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, QuerydslPredicateExecutor<MyEntity> {

}

Usage:

try (Stream<MyEntityView> stream = dao.findBy(predicate, q -> q.as(MyEntityView.class).stream())) {
    stream.forEach(row -> {});
}

Whereas MyEntityView is a projection interface with only some fields of the real entity.

Now the "manual" query, whereas MyEntityView is a real class with a constructor in this case:

try(Stream<FlightCacheGdsView2> stream = new JPAQuery<>(em)
				.select(Projections.constructor(MyEntityView.class,
						QMyEntity.myEntity.field1, QMyEntity.myEntity.field2, QMyEntity.myEntity.field5))
		                .from(QMyEntity.myEntity)
				.where(predicate)
				.stream()) {
    stream.forEach(row -> {});
}

So maybe anybody has an explaination for this performance gain then using JPAQuery manually? I don't think this happens just by chance. Maybe it's a bug?

At the end, both approaches are calling AbstractJPAQuery.stream(), so I wonder why there is a difference at all.

Update: what I just found the reason: the findBy() method creates a query that selects all fields from the database. select myEntity from MyEntity myEntity where....

Whereas the JPAQuery only selects the desired fields for the projection (select field1, field2, field5 from myEntity...).

So probably this is a bug in cases where a Projection interface is passed to the FetchableFluentQuery function?

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Sep 14, 2023
@membersound membersound changed the title JPAQuery with Predicate 50% faster than QuerydslPredicateExecutor JPAQuery executed manually 50% faster than QuerydslPredicateExecutor Sep 14, 2023
@membersound membersound changed the title JPAQuery executed manually 50% faster than QuerydslPredicateExecutor JPAQuery executes Projections 50% faster than QuerydslPredicateExecutor Sep 14, 2023
@mp911de
Copy link
Member

mp911de commented Jan 31, 2025

That should be addressed via #2327. Previously, we've loaded full entities and then applied projections.

@mp911de mp911de closed this as completed Jan 31, 2025
@mp911de mp911de added status: superseded An issue that has been superseded by another and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: superseded An issue that has been superseded by another
Projects
None yet
Development

No branches or pull requests

4 participants