Spring/Hibernate optimization: JPA with @OneToOne mapping
Lately I wanted to see how Hibernate actually construct sql statements. And it seems like it makes somtimes unnecessary joins. Those are my playground's results.
Repo: https://github.com/toficzak/social-app
Setup:
Simple select measure
Repo: https://github.com/toficzak/social-app
Setup:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Entity | |
@Table(name = "users") | |
public class User extends BaseEntity { | |
} | |
@Entity | |
public class Post extends BaseEntity { | |
@NotBlank | |
String message; | |
@NotNull | |
@ManyToOne(fetch = FetchType.LAZY) | |
@JoinColumn(name = "author_id", referencedColumnName = "id") | |
User author; | |
} | |
Post repository consists of 3 methods:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Repository | |
public interface PostRepository extends CrudRepository<Post, Long> { | |
Optional<Post> findTopByAuthorOrderByIdDesc(User author); | |
Optional<Post> findTopByAuthorIdOrderByIdDesc(Long authorId); | |
@Query("from Post where author_id = ?1 order by id desc") | |
Optional<Post> findWithCustomQueryOrderByIdDesc(Long authorId); | |
} |
Sql generated by Hibernate:
How did I measure execution time:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--> By author id: | |
Hibernate: | |
select | |
post0_.id as id1_0_, | |
post0_.author_id as author_i3_0_, | |
post0_.message as message2_0_ | |
from | |
post post0_ | |
left outer join | |
users user1_ | |
on post0_.author_id=user1_.id | |
where | |
user1_.id=? | |
order by | |
post0_.id desc limit ? | |
--> By author: | |
Hibernate: | |
select | |
post0_.id as id1_0_, | |
post0_.author_id as author_i3_0_, | |
post0_.message as message2_0_ | |
from | |
post post0_ | |
where | |
post0_.author_id=? | |
order by | |
post0_.id desc limit ? | |
--> With custom query: | |
Hibernate: | |
select | |
post0_.id as id1_0_, | |
post0_.author_id as author_i3_0_, | |
post0_.message as message2_0_ | |
from | |
post post0_ | |
where | |
author_id=? | |
order by | |
post0_.id desc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
startTime = System.nanoTime(); | |
method(); | |
endTime = System.nanoTime(); | |
duration = (endTime - startTime); | |
results.add(duration); | |
average = results.stream().mapToLong(Long::longValue).average().getAsDouble() |
By author id: 1952090.938
By author (User provided): 1048579.671
By author (User not provided): 1021450.464
By custom query: 935087.347
My custom JPA query is the fastest option - it skips whole User join section. But why is it needed at all? Seems like an error in my design.
My custom JPA query is the fastest option - it skips whole User join section. But why is it needed at all? Seems like an error in my design.
Komentarze
Prześlij komentarz