2009-05-20 33 views
8

Tôi hiện đang thử nghiệm với EJB3 như là một uy tín cho một dự án lớn tại nơi làm việc. Một trong những điều tôi đang xem là truy vấn bộ nhớ đệm.Tại sao truy vấn bộ nhớ đệm với Hibernate làm cho truy vấn chậm hơn mười lần?

Tôi đã tạo một mô hình miền rất đơn giản với chú thích JPA, giao diện kinh doanh @Local và triển khai @Stateless trong EJB-JAR, được triển khai trong một EAR cùng với một ứng dụng web rất đơn giản để thực hiện một số thử nghiệm cơ bản. EAR được triển khai trong cấu hình mặc định JBoss 5.0.1 không có sửa đổi. Điều này rất căng thẳng, và làm việc như mong đợi.

Tuy nhiên, thử nghiệm liên quan đến bộ nhớ đệm truy vấn mới nhất của tôi, và tôi đã nhận một số kết quả kỳ lạ:

  • Tôi có một lớp miền mà chỉ có bản đồ một ID và một giá trị String, và đã tạo ra khoảng 10.000 hàng trong đó đặc biệt bảng
  • trong đậu kinh doanh, có một câu hỏi rất đơn giản, SELECT m TỪ MyClass m
  • Khi không có bộ nhớ cache, điều này thực hiện trong khoảng 400ms trung bình
  • với bộ nhớ cache truy vấn cho phép (thông qua gợi ý về truy vấn), các việc thực hiện đầu tiên của khóa học mất nhiều thời gian hơn một chút, khoảng 1200ms. Các cuộc hành quyết tiếp theo mất trung bình 3500ms!

Điều này khiến tôi bối rối, vì vậy tôi đã bật show_sql của Hibernate để xem nhật ký. Uncached, và trên thực hiện đầu tiên với bộ nhớ cache được kích hoạt, có một SELECT đăng nhập, như mong đợi. Khi tôi sẽ nhận được truy cập bộ nhớ cache, Hibernate ghi lại một SELECT cho mỗi hàng trong bảng cơ sở dữ liệu.

Điều đó chắc chắn sẽ giải thích thời gian thực hiện chậm, nhưng bất kỳ ai cũng có thể cho tôi biết tại sao điều này xảy ra?

+0

Bạn có thể tìm thấy một số thông tin hữu ích trên blog của tôi về bộ nhớ cache truy vấn tại đây: * http://tech.puredanger.com/2009/07/10/hibernate-query-cache/ –

Trả lời

16

Cách bộ nhớ cache truy vấn hoạt động là nó chỉ lưu trữ số của các đối tượng được truy vấn trả về. Vì vậy, câu lệnh SELECT ban đầu của bạn có thể trả về tất cả các đối tượng, và Hibernate sẽ trả lại cho bạn và nhớ ID của nó.

Lần sau khi bạn phát hành truy vấn, Hibernate đi qua danh sách ID và nhận ra nó cần phải thực hiện dữ liệu thực tế. Vì vậy, nó đi trở lại vào cơ sở dữ liệu để nhận phần còn lại. Và nó thực hiện một SELECT cho mỗi hàng, đó chính xác là những gì bạn đang thấy.

Bây giờ, trước khi bạn nghĩ, "tính năng này rõ ràng là bị hỏng", lý do nó hoạt động theo cách này là bộ nhớ cache truy vấn được thiết kế để làm việc trong buổi hòa nhạc với bộ nhớ cache cấp thứ hai. Nếu các đối tượng được lưu trữ trong bộ nhớ cache L2 sau truy vấn đầu tiên, thì Hibernate sẽ nhìn vào đó thay vì đáp ứng các yêu cầu cho mỗi ID.

Tôi đặc biệt khuyên bạn nên chọn sách Java Persistence with Hibernate để tìm hiểu thêm về điều này. Chương 13 nói riêng bao gồm tối ưu hóa các truy vấn và cách sử dụng bộ nhớ cache một cách hiệu quả.

+1

Tuyệt vời, tôi sẽ thử bật Bộ nhớ cache cấp 2 cũng vậy. Tôi yêu nơi này :-) –

+0

Cuốn sách này đã được một vài năm, nó vẫn còn cập nhật? –

+0

Câu hỏi hay, Nathan. Tôi đang sử dụng Hibernate 3.2 và mọi thứ dường như hoàn toàn cập nhật với tôi. Cuốn sách cũng bao gồm tất cả các chú giải JPA 1.0, cũng như bao gồm cả phần giới thiệu về JBoss Seam. Có bất kỳ tính năng mới quan trọng nào trong Hibernate 3.3 có thể không được đề cập không? –

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