N+1 query problem
Ngo Tran Quoc Tuan (Liam)
? Software Developer | Java Spring boot | Database | Studies Performance Tuning at Wecommit Vi?t Nam. Let's connect!
1. V?n ?? N+1 query là gì
V?n ?? N+1 queries x?y ra khi m?t ORM nh? Hibernate th?c thi m?t truy v?n SQL ?? truy xu?t th?c th? chính t? m?i quan h? parent-child và sau ?ó m?t truy v?n SQL cho t?ng ??i t??ng child.
V?n ?? N+1 queries kh?ng riêng cho JPA và Hibernate vì b?n có th? g?p ph?i v?n ?? này ngay c? khi b?n ?ang s? d?ng các c?ng ngh? truy c?p d? li?u khác.
2. Khi s? d?ng Hibernate
Gi? s? chúng ta có các b?ng c? s? d? li?u post và post_comments sau ?ay t?o thành m?i quan h? b?ng one-to-many:
Chúng ta s? t?o 4 hàng trong b?ng post nh? sau:
Và chúng ta c?ng s? t?o 4 b?n ghi trong b?ng post_comment child:
2.1. V?n ?? N+1 queries khi s? d?ng Plain SQL
V?n ?? truy v?n N+1 có th? ???c gay ra b?ng cách s? d?ng b?t k? c?ng ngh? truy c?p d? li?u nào, ngay c? v?i Plain SQL( Cau truy v?n SQL th?ng th??ng).
N?u b?n select post_comments b?ng truy v?n SQL này:
Và sau ?ó, b?n quy?t ??nh fetch title trong b?ng post liên quan cho m?i post_comment:
Ta s? kích ho?t v?n ?? N+1 queries vì thay vì m?t truy v?n SQL, b?n ?? th?c thi 5 (1 + 4):
Vi?c kh?c ph?c v?n ?? N+1 query trong tr??ng h?p này r?t d? dàng. T?t c? nh?ng gì ta c?n làm là trích xu?t t?t c? d? li?u ta c?n trong truy v?n SQL g?c nh? th? này:
L?n này, ch? m?t truy v?n SQL ???c th?c thi ?? tìm n?p t?t c? d? li?u mà chúng ta c?n.
2.2. V?n ?? N+1 queries v?i Hibernate
Khi s? d?ng Hibernate, có m?t s? cách ta có th? gay ra v?n ?? N+1 queries, vì v?y ?i?u quan tr?ng là ta ph?i bi?t cách tránh nh?ng tình hu?ng này.
??i v?i các ví d? ti?p theo, h?y xem xét vi?c chúng ta ?ang ánh x? các b?ng post và post_comments t?i các entities sau:
Code ánh x? JPA s? nh? th? này:
2.2.1 FetchType.EAGER
S? d?ng FetchType.EAGER m?t cách ng?m ??nh ho?c r? ràng cho các liên k?t JPA là m?t y t??ng t?i vì ta s? tìm n?p nhi?u d? li?u h?n mà ta c?n. H?n n?a, chi?n l??c FetchType.EAGER c?ng d? g?p ph?i các v?n ?? v? truy v?n N+1.
Th?t kh?ng may, các liên k?t?@ManyToOne?và?@OneToOne?s? d?ng FetchType.EAGER theo m?c ??nh, vì v?y n?u code ánh x? c?a chúng ta tr?ng nh? th? này:
Chúng ta ?ang s? d?ng chi?n l??c FetchType.EAGER và m?i khi ta quên s? d?ng JOIN FETCH khi t?i m?t s? th?c th? PostComment b?ng truy v?n JPQL ho?c Criteria API query:
Ta s? kích ho?t v?n ?? N+1 queries:
L?u y các cau l?nh SELECT b? sung ???c th?c thi vì liên k?t v?i b?ng post ph?i ???c tìm n?p tr??c khi tr? v? list các entities PostComment.
Kh?ng gi?ng nh? plan tìm n?p m?c ??nh mà b?n ?ang s? d?ng khi g?i ph??ng th?c?find?c?a EntityManager class, truy v?n JPQL ho?c API tiêu chí xác ??nh m?t plan r? ràng mà Hibernate kh?ng th? thay ??i b?ng cách t? ??ng thêm JOIN FETCH. Vì v?y, ta c?n ph?i làm ?i?u ?ó m?t cách th? c?ng.
N?u ta hoàn toàn kh?ng c?n d? li?u liên k?t ? b?ng post, ta s? kh?ng g?p may khi s? d?ng FetchType.EAGER vì kh?ng có cách nào ?? tránh tìm n?p nó. ?ó là ly do t?i sao nên s? d?ng FetchType.LAZY theo m?c ??nh s? t?t h?n.
Tuy nhiên, n?u ta mu?n s? d?ng d? li?u liên k?t ? b?ng post, thì ta có th? s? d?ng JOIN FETCH ?? tránh v?n ?? truy v?n N+1:
L?n này, Hibernate s? th?c thi m?t cau l?nh SQL:
2.2.2 FetchType.LAZY
Ngay c? khi ta chuy?n sang s? d?ng FetchType.LAZY m?t cách r? ràng cho t?t c? các liên k?t, ta v?n có th? g?p ph?i v?n ?? N+1 queries.
L?n này, b?ng post ???c ánh x? nh? th? này:
Bay gi?, khi ta fetch các PostComment entities:
Hibernate s? th?c thi m?t cau l?nh SQL duy nh?t:
Tuy nhiên, n?u sau ?ó, b?n s? g?i t?i liên k?t c?a b?ng post mà ta ?ang ?ánh d?u là lazy-loaded:
Ta s? g?p v?n ?? N+1 queries:
Vì các liên k?t v?i b?ng post ???c fetch m?t cách lazy nên m?t cau l?nh SQL ph? s? ???c th?c thi khi truy c?p vào liên k?t này.
M?t l?n n?a, cách kh?c ph?c bao g?m vi?c thêm m?nh ?? JOIN FETCH vào truy v?n JPQL:
Và gi?ng nh? trong ví d? FetchType.EAGER, truy v?n JPQL này s? t?o ra m?t cau l?nh SQL duy nh?t.
? Software Developer | Java Spring boot | Database | Studies Performance Tuning at Wecommit Vi?t Nam. Let's connect!
1 个月Quá là tuy?t v?i, ?ay th?t s? là 1 bài vi?t c?c kì giá tr? và tam huy?t