2009-03-05 44 views
43

hiệp hội Hầu hết Hibernate hỗ trợ "lấy" tham số:Hibernate fetching strategy - khi nào sử dụng "join" và khi nào thì dùng "select"?

fetch="join|select" 

với "chọn" là giá trị mặc định.

Cách quyết định sử dụng liên kết nào?

Tôi đã thử thay đổi tất cả từ "chọn" thành "tham gia" ứng dụng rộng - số lượng truy vấn được tạo giảm có thể 10 lần nhưng hiệu suất vẫn giữ nguyên (thậm chí trở nên tồi tệ hơn một chút).

Cảm ơn.

+0

Tham gia sẽ thử lại tất cả thông tin trong một câu lệnh chọn trong khi ở trường hợp khác nếu bạn tìm nạp = "chọn" Hibernate sẽ chuyển câu lệnh chọn thứ hai để tìm nạp bộ sưu tập được liên kết trừ khi bạn tắt tìm nạp lười bằng cách chỉ định lazy = "false "bạn có thể tìm thêm chi tiết tại đây http://javawebtutorial.blogspot.in/2013/09/hibernate-fetching-strategies.html – user528050

Trả lời

38

Tham gia có nghĩa vụ giải quyết vấn đề n + 1. Nếu bạn có 10 cha mẹ, mỗi người có 10 trẻ em, tham gia sẽ yêu cầu một truy vấn và chọn sẽ yêu cầu 11 (một cho cha mẹ và một cho con của mỗi phụ huynh). Điều này có thể không phải là một vấn đề lớn nếu cơ sở dữ liệu trên cùng một máy chủ như ứng dụng hoặc nếu mạng thực sự nhanh, nhưng nếu có độ trễ trong mỗi cuộc gọi cơ sở dữ liệu, nó có thể tăng lên. Phương thức kết nối kém hiệu quả hơn một chút đối với truy vấn ban đầu bởi vì bạn đang sao chép các cột cha trong mỗi hàng, nhưng bạn chỉ thực hiện một chuyến đi khứ hồi tới cơ sở dữ liệu.

Nói chung, nếu tôi biết tôi sẽ cần con cái của tất cả phụ huynh, tôi sẽ tham gia. Nếu tôi chỉ cần những đứa con của một vài bố mẹ, tôi sử dụng lựa chọn.

+7

Hm, tôi đã thử nó trên sản xuất (chúng tôi có máy chủ db từ xa với nô lệ) và hành vi vẫn chính xác tương tự - một chút tồi tệ hơn "chọn". Để trợ giúp với vấn đề n + 1, chúng tôi đang sử dụng "default_batch_fetch_size", vì vậy nó sẽ chạy các truy vấn chọn theo lô, chứ không phải từng câu hỏi một. – serg

9

Chọn sẽ tìm nạp các mục con bằng cách phát hành truy vấn mới cho cơ sở dữ liệu cho chúng. Tham gia sẽ tìm nạp các mục con bằng cách nối chúng vào truy vấn của cha mẹ. Vì vậy, đó là lý do tại sao bạn thấy hiệu suất tương tự, ngay cả khi giảm số lượng truy vấn.

Chọn:

SELECT * FROM parent WHERE id=(whatever) 
SELECT * FROM child WHERE id=(parent.child.id) 

Tham gia:

SELECT * 
FROM parent 
LEFT OUTER JOIN child ON parent.child.id=child.id 
WHERE parent.id=(whatever) 

Như để khi nào cần sử dụng một trong khác ... Không phải toàn bộ chắc chắn. Nó có thể phụ thuộc vào hệ thống cơ sở dữ liệu. Nếu một người luôn luôn tốt hơn người kia, tôi nghi ngờ họ sẽ bận tâm để cung cấp cho bạn tùy chọn! Nếu bạn thấy hiệu suất tương tự cho mỗi người, tôi sẽ không lo lắng về nó.

1

fetching = "join" Nếu bạn tìm nạp = "join", nó sẽ truy xuất tất cả thông tin trong một câu lệnh chọn duy nhất.

fetching = "select" nếu bạn muốn paas câu lệnh chọn thứ hai để tìm tập hợp được liên kết hơn trong trường hợp đó bạn sẽ sử dụng fetch = "select".

nguồn: Hibernate Fetching Strategies

0

Mọi người luôn nói về hiệu suất sử dụng hit lấy = THAM GIA. Nhưng như tôi nghĩ, điều quan trọng là chúng tôi phải hiểu số lượng hồ sơ cha mẹ/con mà chúng tôi đang tìm nạp:

Nếu bạn muốn tìm nạp bản ghi gốc duy nhất và mong đợi nó không có nhiều con, tôi sẽ đề nghị bạn sử dụng fetch = SELECT.

Nếu bạn muốn lấy tất cả hồ sơ cha mẹ kể cả trẻ em của nó, sau đó nó sẽ được tốt hơn để đi cho lấy = THAM GIA

Chỉ cần thêm một lưu ý rằng, nếu hồ sơ được uể oải lấy trẻ em (lười biếng = true), sau đó nó sẽ không làm cho bất kỳ ý nghĩa của việc sử dụng fetch = JOIN vì tất cả các bản ghi cha và con được tải trong một shot duy nhất.

0

Nếu cha mẹ có nhiều con và những đứa trẻ đó có nhiều thứ khác, thì trong trường hợp này, 'tham gia' ban đầu có thể làm tắc nghẽn mạng. Đề xuất của tôi là sử dụng 'chọn' trong trường hợp này để tách các lựa chọn.

0

THAM GIA được ưu tiên, thường là vì lý do hiệu suất.

Một lý do để sử dụng SELECT là nếu bạn đang phân trang kết quả (thiết lập một bù đắp và giới hạn) có mối quan hệ nhiều-nhiều. Nếu bạn sử dụng JOIN, thực thể gốc sẽ xuất hiện nhiều lần nếu nó chứa nhiều con nhiều và nhiều "bản sao" này đếm ngược với giới hạn của bạn (ngay cả khi Hibernate sụp đổ chúng sau khi sử dụng DISTINCT_ROOT_ENTITY).

Các vấn đề liên quan