2015-09-15 13 views
7

Tôi đã đấu tranh trong vài ngày với một truy vấn trên hibernate dựa vào cơ sở dữ liệu Oracle. Một cái gì đó như thế này được sử dụng để nạp các bản ghi vào lưới.Hibernate tham số sql truy vấn các phiên oracle chậm và hoạt động

SELECT 
    fields 
FROM 
    tables and JoinedTables 
WHERE 
     Field1 >= :value1 
    AND Field2 = :value2 
    AND Field3 = :value3 
Order By MaintTable.Id Desc 

Sử dụng phương pháp này trong phương pháp Spring Java + Hibernate 4.2.

SQLQuery query = (SQLQuery) session.createSQLQuery(querySql) 
           .addEntity(CertificateViewEnt.class) 
           .setParameter("value1", firstCertificateRecordDate) 
           .setParameter("value2", certType.toUpperCase()) 
           .setParameter("value3", deleted? 1:0);  

Mỗi trường được lọc được lập chỉ mục chính xác và tạo Chỉ mục chức năng trên Maintable.Id Descendent để cải thiện hiệu suất.

Lúc đầu, tôi nghĩ rằng nó là hồ bơi phiên/kết nối không được quản lý một cách chính xác, vì vậy tôi đã thay đổi để StatelessSession và thêm session.close này():

query.setCacheable(false) 
       .setTimeout(30) 
       .setReadOnly(true); 
... 
... 
//Pagination 
query.setMaxResults(rows); 
query.setFirstResult(HelperMethod(page, rows)); 

result = (List<CertificateViewEnt>) query.list(); 
session.close(); 
return result; 

Nó không giải quyết nó. Truy vấn chạy một cặp lần ok, nhưng vì một số lý do không xác định và sử dụng các giá trị đã chạy trước đó với thành công, treo, thoát phiên mở trong Oracle (status = ACTIVE) và không thành công khi hết thời gian chờ. Truy vấn tương tự đang chạy với Oracle trên bất kỳ máy khách SQL nào và hàng chục lần với tất cả các kết hợp có thể có của các tham số thực hiện với hiệu suất cực đại, khoảng 400 mili giây, cho 10 bản ghi tại một thời điểm.

Sau khi đọc một số bài viết ở đây và ở đó, link1 [Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query Link2: [query hangs oracle 10g

tôi supected của QueryPlan kém đang được sử dụng bởi Hibernate và quyết định loại bỏ tất cả các bộ lọc sử dụng các tham số ràng buộc và cũng không giải quyết, mặc dù nó tốt hơn một chút. Sau một thời gian bị treo cổ khi di chuyển đến các trang khác như trang 1, 2,3,4, ...

Sau tất cả những gì, tôi nghi ngờ của SQL được tạo ra bằng phương pháp Hibernate của

query.setMaxResults(rows) 
query.setFirstResult(SomeHelperMethod(page, rows)); 

Bởi vì cưa trong nhật ký rằng họ đã được chuyển thành các tham số liên kết với Oracle.

 ... 
     Order By Certificado.Id Desc) row_ 
     where rownum <= ?) 
    where rownum_ > ? 

Tôi cũng thấy điều này trong Trace Log

2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX(

và điều này:

2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [2] as [VARCHAR] - E 
2015-09-15 14:09:53 DEBUG Loader:2031 - bindNamedParameters() 0 -> deleted [3] 
2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [3] as [INTEGER] - 0 
2015-09-15 14:09:53 TRACE Loader:1931 - Bound [7] parameters total 
/* 
SLOW here !!! Around 3 secs when query runs in ~0,300 secs via SQL client. 
And ACTIVE sessions are left running in Oracle. 
*/ 
2015-09-15 14:09:56 TRACE JdbcCoordinatorImpl:397 - Registering result set [[email protected]] 
2015-09-15 14:09:56 TRACE Loader:943 - Processing result set 

Cuối cùng tôi đã phải từ bỏ tất cả các params ràng buộc Hibernate và thực hiện pagination tính tùy chỉnh và viết tất cả các SQL để truy xuất các hàng trang và nó chạy và quản lý các phiên db một cách chính xác.

Vì vậy, Câu hỏi của tôi là: Hibernate làm behing những cảnh nào ngăn truy vấn chạy khi nó chạy trên cơ sở dữ liệu? Có bất kỳ vấn đề đã biết nào với các truy vấn tham số ràng buộc không?

Tôi thực sự không muốn viết tất cả mã SQL và buộc phân tích cú pháp khó SQL này, khi tôi có các tham số liên kết.

Một số ghi chú về môi trường: Tomcat và Oracle nằm trên cùng một máy chủ.Vì vậy, kết nối mạng không phải là vấn đề

Hibernate phiên bản 4.2.15 chính thức

Bảng có khoảng 300k REC trong cơ sở dữ liệu dev (1,5m trên sản xuất) và hiển thị các trang 10, 20, 50 REC tại một thời điểm , được sắp xếp theo Primary Key Desc (Chuỗi được tạo ra)

Hy vọng một số chuyên gia Hibernate có thể giúp tôi về điều này để tôi vẫn có thể tin tưởng các truy vấn Hibernate trên các dự án cơ sở dữ liệu lớn. Cảm ơn trước.

+0

Có cùng vấn đề. Trong MySQL Workbench, truy vấn mất 0 ms. Trong Hibernate phải mất 1500ms. –

+0

Lấy tất cả các tham số Hibernate và tự xây dựng truy vấn SQL với tất cả các tham số được đặt trong chuỗi SQL. Nó làm việc cho tôi. Giống như là một truy vấn trường học cũ của JDBC. –

+0

Cảm ơn lời khuyên. Chắc chắn đáng để thử! –

Trả lời

1

Tôi không biết đây có phải là vấn đề của bạn hay không, nhưng Oracle xem xét các giá trị biến liên kết khi phân tích cú pháp truy vấn và sau đó lưu kế hoạch truy vấn để thực hiện trong tương lai để nó không phải phân tích truy vấn mỗi lần truy vấn chạy với một tập hợp các biến ràng buộc mới. Nhưng mỗi một lần và một lúc truy vấn được phân tích cú pháp lại. Nếu một số giá trị biến liên kết bất thường xảy ra trong khi phân tích cú pháp thì kế hoạch xấu được lưu trữ và sử dụng. Nó là loại lời nguyền của các biến liên kết. Chúng làm giảm phân tích cú pháp nhưng có thể lật kế hoạch xung quanh các giá trị biến liên kết không điển hình khi các truy vấn được phân tích cú pháp một lần nữa. Gợi ý có thể hữu ích. Chúng tôi sử dụng Hồ sơ SQL để khóa trong kế hoạch truy vấn với các biến liên kết có xu hướng thay đổi gói. Đôi khi bạn có thể tùy chỉnh thời gian và cách các số liệu thống kê trình tối ưu hóa được thu thập sao cho một kế hoạch tốt được tạo bất kể giá trị nào được chuyển vào các biến liên kết.

Dù sao đi nữa, thứ gì đó mà tôi thấy mọi lúc và có thể hoặc không phải là vấn đề của bạn.

Bobby

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