2012-04-25 39 views
14

Im viết ứng dụng web bằng Hibernate 3.Hibernate Performance Thực hành tốt nhất?

Vì vậy, sau một thời gian tôi nhận thấy có điều gì đó chậm. Vì vậy, tôi đã thử nghiệm profiler hibernate và thấy rằng hibernate sẽ làm cho một cách vô lý nhiều cuộc gọi db cho hoạt động đơn giản. Lý do là ofcourse rằng tôi tải một đối tượng (đối tượng này có một số "cha mẹ") và những "cha mẹ" có "cha mẹ" khác. Vì vậy, cơ bản hibernate tải tất cả, mặc dù tôi chỉ cần các đối tượng cơ bản. Ok, vì vậy tôi đã xem xét việc tải chậm. Mà dẫn tôi vào Lazyloading-ngoại lệ, bởi vì tôi có một webapp MVC.

Vì vậy, bây giờ tôi hơi bối rối về cách tiếp cận tốt nhất của tôi cho điều này là gì. Về cơ bản tất cả những gì tôi cần là cập nhật một trường đơn trên một đối tượng. Tôi đã có khóa đối tượng.

Tôi có nên: 1. Tìm hiểu về tải trọng. Và sau đó viết lại ứng dụng của tôi cho chế độ xem phiên mở? 2. Đào sâu vào tải. Và sau đó viết lại dao của tôi để cụ thể hơn. Ví dụ. viết DAO-phương pháp mà sẽ trả về các đối tượng instanciated với chỉ whats cần thiết cho từng trường hợp sử dụng? Có thể có rất nhiều phương pháp bổ sung ... 3. Scratch hibernate và tự mình làm? 4. Không thể thực sự nghĩ về các giải pháp khác ngay bây giờ. Bất kỳ đề xuất?

Phương pháp hay nhất là gì?

Trả lời

25
  • Không sử dụng kết nối trừ khi thực sự cần thiết. Họ sẽ không cho phép bạn sử dụng tải không tải xuống, cũng như không sử dụng bộ nhớ cache cấp 2 cho các liên kết
  • Sử dụng lazy = "extra" cho các bộ sưu tập lớn, nó sẽ không truy xuất tất cả các phần tử cho đến khi bạn hỏi, bạn cũng có thể sử dụng kích thước() Ví dụ, không lấy các phần tử từ DB
  • Sử dụng phương thức load() nếu có thể vì nó không đưa ra truy vấn chọn cho đến khi nó được yêu cầu. Ví dụ. nếu bạn có một Sách và một tác giả và bạn muốn kết hợp chúng lại với nhau, điều này sẽ sẽ không phát hành bất kỳ lựa chọn, chỉ chèn duy nhất:

    Book b = (Book) session.load(Book.class, bookId); 
    Author a = (Author) session.load(Author.class, authorId); 
    b.setAuthor(a); 
    session.save(b); 
    
  • Sử dụng tên truy vấn (trong file hbm của bạn hoặc trong @NamedQuery) để chúng không được phân tích cú pháp trong mỗi truy vấn.Không sử dụng Tiêu chuẩn API cho đến khi nó yêu cầu (nó làm cho không thể sử dụng bộ nhớ cache PreparedStatement trong trường hợp này)

  • Sử dụng OSIV trong ứng dụng web của bạn vì nó sẽ tải dữ liệu chỉ khi/nếu nó cần thiết
  • Sử dụng chỉ đọc chế độ cho các lựa chọn chỉ: session.setReadOnly(object, true). Điều này sẽ làm cho Hibernate không giữ lại ảnh gốc của thực thể được chọn trong ngữ cảnh liên tục để kiểm tra thêm bẩn.
  • Bộ nhớ cache cấp 2 của người dùng và Bộ nhớ cache truy vấn cho dữ liệu chỉ đọc và chỉ đọc.
  • Sử dụng FlushMode.COMMIT thay vì AUTO để Hibernate không phát hành trước khi cập nhật, nhưng hãy sẵn sàng rằng điều này có thể dẫn đến dữ liệu cũ được ghi (mặc dù Optimistic Locking có thể giúp bạn).
  • Hãy xem xét tìm nạp hàng loạt (kích thước lô) để chọn một số thực thể/bộ sưu tập cùng một lúc thay vì phát hành các truy vấn riêng biệt cho từng mục.
  • Thực hiện các truy vấn như 'chọn thực thể mới (id, someField) từ thực thể' để chỉ truy xuất các trường bắt buộc. Hãy xem biến thế kết quả.
  • Sử dụng các thao tác theo lô (như xóa) nếu cần
  • Nếu bạn sử dụng truy vấn gốc, hãy chỉ định rõ ràng vùng nhớ cache nào sẽ bị vô hiệu (theo mặc định - tất cả).
  • Hãy xem đường dẫn vật chất và bộ lồng nhau cho cấu trúc giống cây.
  • Đặt c3p0.max_statements để bật bộ nhớ cache PreparedStatment trong hồ bơi và bật bộ nhớ cache của DB nếu nó bị tắt theo mặc định.
  • Sử dụng StatelessSession nếu có thể, nó vượt qua kiểm tra bẩn, tầng, chặn vv
  • Không sử dụng pagination (setMaxResults(), setFirstResult()) cùng với truy vấn có chứa tham gia vào bộ sưu tập, điều này sẽ dẫn đến tất cả các hồ sơ kéo từ cơ sở dữ liệu và phân trang sẽ xảy ra trong bộ nhớ của Hibernate. Nếu bạn muốn phân trang, lý tưởng là bạn không nên sử dụng các phép nối. Nếu bạn không thể thoát khỏi nó, một lần nữa - sử dụng tìm nạp hàng loạt.

Thực tế có rất nhiều thủ thuật nhưng tôi không thể nhớ thêm tại thời điểm này.

+0

OSIV bạn có thể giải thích rằng tôi không nhận được –

1

Tôi tin rằng bạn muốn xem lại điều này section in the Hibernate manual.

Tôi mong rằng vấn đề ban đầu của bạn về "... nhiều cuộc gọi db không hợp lý ..." là một ví dụ về những gì họ gọi là "N + 1 chọn vấn đề". Nếu vậy, họ đã có những lựa chọn về cách đối phó với nó.

  1. Làm cho loại tìm nạp Tham gia. Sau đó, bạn sẽ có một lựa chọn duy nhất với một số tham gia, giả sử không có bộ sưu tập trung gian.
  2. Làm tải chậm.
  3. Có lẽ một số khác, ví dụ như FetchProfiles mà tôi không có kinh nghiệm.

Hai loại đầu tiên có thể được chỉ định ở cấp liên kết và loại tìm nạp có thể được ghi đè ở cấp truy vấn. Bạn sẽ có thể nhận được truy vấn của bạn để chỉ làm những gì bạn cần, không nhiều hơn, và làm điều đó với một truy vấn SQL 'tốt' với những công cụ này.

3

Như tôi đã giải thích trong this article hoặc High-Performance JavaPersistence book của tôi, có rất nhiều điều bạn có thể làm để tăng tốc độ lên hiệu suất Hibernate, như:

  1. Enabling SQL statement logging để bạn có thể xác nhận tất cả các báo cáo và thậm chí detect N+1 query problems during testing.
  2. Quản lý và giám sát kết nối cơ sở dữ liệu bằng cách sử dụng FlexyPool
  3. JDBC batching để giảm số lượng vòng cần thiết để gửi câu lệnh INSERT, UPDATE và DELETE.
  4. JDBC Statement caching
  5. tối ưu nhận dạng JPA như pooled or pooled-lo
  6. Chọn loại cột nhỏ gọn
  7. Sử dụng các mối quan hệ ngay: bidirectional @OneToMany instead of unidirectional one, sử dụng @MapsId for @OneToOne, using Set for @ManyToMany
  8. Sử dụng inheritance the right waypreferring SINGLE_TABLE for performance reasons
  9. Minding the Persistence Context size and avoiding long-running transactions
  10. Sử dụng hệ điều hành bộ nhớ đệm , Bộ nhớ đệm DB trước khi chuyển sang bộ nhớ cache cấp 2 h cũng rất hữu ích để off-load nút Primary khi thực hiện cơ sở dữ liệu sao chép
  11. Giải phóng khả năng truy vấn cơ sở dữ liệu thông qua SQL native queries
  12. Chia viết giữa nhiều one-to-one tổ chức để reduce optimistic locking false positives và có được một cơ hội tốt hơn để đạt cache cơ sở dữ liệu thậm chí khi sửa đổi một số thực thể nhất định.
Các vấn đề liên quan