2009-11-23 53 views
9

Gần đây tôi đã có một hiện tượng khá lạ. Đã có được một số bao gồm tham gia trên nhiều bảng với điều kiện WHERE khác nhau. Tôi đã thực hiện truy vấn đầu tiên với API tiêu chí của hibernate. Nó đã tạo một cách chính xác câu lệnh SQL đã chuẩn bị được yêu cầu nhưng khá chậm. Thực hiện lại sau đó toàn bộ truy vấn bằng HQL. Đã khá khó chịu để làm điều đó nhưng kết quả thực hiện nhanh hơn nhiều so với API tiêu chí. Có ai biết lý do cho hành vi đó không? Tôi giả định rằng khung tiêu chuẩn và HQL sử dụng cùng một cơ sở mã để chuyển đổi nó thành SQL.Truy vấn Hibernate so với Hiệu suất Tiêu chí

Đây là truy vấn:

select count(*) from R r where r.ISREPLACEDBY = 0 
and r.STATUS='OK' and r.A = ? 
and r.C in 
    (select distinct RC from CX cx where cx.FROMDATE >= ? and cx.FROMDATE <=?) 
+0

bạn có thể hiển thị HQL và Tiêu chuẩn truy vấn? –

+0

Truy vấn phụ thuộc vào các tham số. Một trong những quy tắc đơn giản giống như sau: chọn số (*) từ R r trong đó r.ISREPLACEDBY = 0 và r.STATUS = 'OK' và r.A =? và r.C trong (chọn RC riêng biệt từ CX cx, nơi cx.FROMDATE> =? và cx.FROMDATE <=?) – bertolami

Trả lời

17

Tôi đoán cuối cùng tôi đã tìm ra lý do. Dường như api tiêu chí tạo ra các tên biến mới mỗi lần một câu lệnh chuẩn bị được thực thi. Cơ sở dữ liệu (trong trường hợp của chúng tôi, DB2) tính toán sau đó một kế hoạch thực thi truy vấn mới mỗi khi câu lệnh được thực hiện. Mặt khác, HQL sử dụng cùng tên biến, cho phép cơ sở dữ liệu sử dụng lại các kế hoạch thực thi truy vấn.

0

Tôi thường tin rằng HQL là rất gần tối ưu, vì nó là SQL gần thẳng với một vài thay. Tôi cho rằng bản dịch từ HQL sang SQL chỉ là thay thế; API tiêu chí có thể tạo HQL để sau đó được chuyển đổi. Nói chung HQL là đặt cược tốt nhất của bạn.

+2

Thực ra, tiêu chí dịch trực tiếp sang SQL. ví dụ. Criterion.toSqlString – qualidafial

+0

Điều đó thực sự không đúng. Đầu tiên nó tạo ra HQL sau đó được phân tích cú pháp. – mnp

0

Tiêu chuẩn Hibernate Sử dụng phản ánh để tạo SQL statments

+0

Một vấn đề khác với API tiêu chí là nó tạo ra HQL mỗi lần (vì nó có thể khác nhau mỗi lần). HQL này cũng được dịch sang SQL mỗi lần. Bản dịch này cố gắng tải một số mã thông báo thông qua trình nạp lớp (ví dụ: generatedBla0) sẽ ném ra một ClassNotFoundException. Đây là hoạt động khá tốn kém khi nó đi qua tất cả các trình nạp lớp trước khi trình cuối cùng có thể ném một ngoại lệ và cũng liên quan đến một số khóa trong trình nạp lớp ảnh hưởng lớn đến hiệu suất. Quên đề cập đến rằng do một số nguyên lỗi có thể được chèn vào SQL thay vì params. – mnp

3

Tiêu chuẩn, về mặt lý thuyết nên có ít bước đầu hơn một truy vấn HQL (trừ cho các truy vấn tên, mà tôi sẽ nhận được). Điều này là do Tiêu chí không cần phải phân tích cú pháp bất cứ điều gì. Truy vấn HQL được phân tích bằng trình phân tích cú pháp dựa trên ANTLR và sau đó kết quả là AST được chuyển thành SQL. Tuy nhiên, với HQL/JPAQL bạn có thể định nghĩa các truy vấn có tên, nơi mà SQL được tạo khi SessionFactory khởi động. Về lý thuyết, truy vấn được đặt tên có ít chi phí hơn tiêu chí. Vì vậy, về chi phí của thế hệ SQL, chúng tôi có:

  1. Đặt tên truy vấn HQL/JPAQL - SQL chỉ xảy ra một lần.
  2. Tiêu chí - Không cần phải phân tích cú pháp trước khi tạo.
  3. (không được đặt tên) Truy vấn HQL/JPAQL - Phân tích cú pháp, sau đó tạo. Điều đó nói rằng, việc lựa chọn một kỹ thuật truy vấn dựa trên chi phí phân tích và tạo SQL có lẽ là một sai lầm trong quan điểm của tôi. Chi phí này thường rất nhỏ khi so sánh với việc thực hiện truy vấn thực sự trên máy chủ cơ sở dữ liệu thực với dữ liệu thực. Nếu chi phí này thực sự hiển thị khi lập hồ sơ ứng dụng thì có thể bạn nên chuyển sang truy vấn được đặt tên.

Dưới đây là những điều tôi cân nhắc khi quyết định giữa Tiêu chuẩn và HQL/JPAQL:

  • Trước tiên, bạn phải quyết định nếu bạn OK với việc có một sự phụ thuộc vào API Hibernate độc ​​quyền tại của bạn mã. JPA không có Tiêu chí.
  • Tiêu chí thực sự tốt trong việc xử lý nhiều thông số tìm kiếm tùy chọn chẳng hạn như bạn có thể tìm thấy trên một trang web điển hình với một biểu mẫu tìm kiếm nhiều tham số '. Với HQL, các nhà phát triển có khuynh hướng tack vào các mệnh đề với StringBuilder (tránh điều này!). Với tiêu chí, bạn không cần phải làm điều đó.
  • HQL/JPAQL có thể được sử dụng cho hầu hết mọi thứ khác, vì mã có xu hướng trở nên nhỏ hơn và dễ dàng hơn cho nhà phát triển để hiểu.
  • Truy vấn thường xuyên có thể được chuyển thành truy vấn được đặt tên nếu bạn sử dụng HQL. Tôi thích làm điều này sau, sau khi một số hồ sơ.

Bạn có thể đọc một số thông tin bổ sung ở đây http://tech.puredanger.com/2009/07/10/hibernate-query-cache/

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