2008-10-21 36 views
8

Làm cách nào để tận dụng khả năng của MySQL để lưu trữ các câu lệnh đã chuẩn bị? Một lý do để sử dụng các câu lệnh đã chuẩn bị là không cần phải gửi chính câu lệnh đã chuẩn bị nhiều lần nếu câu lệnh được chuẩn bị tương tự sẽ được sử dụng lại.Làm thế nào để sử dụng MySQL chuẩn bị báo cáo bộ nhớ đệm?

Class.forName("com.mysql.jdbc.Driver"); 
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mydb" + 
     "?cachePrepStmts=true", "user", "pass"); 
for (int i = 0; i < 5; i++) { 
    PreparedStatement ps = conn.prepareStatement("select * from MYTABLE where id=?"); 
    ps.setInt(1, 1); 
    ps.execute(); 
} 
conn.close() 

Khi chạy ví dụ Java ở trên, tôi thấy 5 cặp Chuẩn bị và Thực thi lệnh trong tệp nhật ký mysqld. Việc chuyển bài tập ps ra ngoài vòng lặp dẫn đến một lệnh Chuẩn bị và Thực thi 5 tất nhiên. Tham số kết nối "cachePrepStmts = true" dường như không tạo ra bất kỳ sự khác biệt nào ở đây.
Khi chạy một chương trình tương tự bằng cách sử dụng Spring và Hibernate số lượng lệnh Chuẩn bị gửi (1 hoặc 5) phụ thuộc vào việc tham số kết nối cachePrepStmts có được bật hay không. Làm thế nào để Hibernate thực thi các câu lệnh đã chuẩn bị để tận dụng lợi thế của thiết lập cachePrepStmts? Có thể bắt chước điều này bằng JDBC thuần túy không?
Tôi đã chạy trên MySQL Server 4.1.22 và mysql-connector-java-5.0.4.jar

Trả lời

2

Có thể bắt chước sử dụng JDBC tinh khiết này?

Đây có phải là thực tế những gì bạn đã thực hiện bằng cách di chuyển cuộc gọi tuyên bố chuẩn bị của bạn ra khỏi vòng lặp?

Tôi có thể hiểu sai cách bộ nhớ cache MySQL hoạt động, nhưng tệp nhật ký có nhất thiết phải báo cáo công việc của bộ đệm không? Có thể là Spring hoặc Hibernate có bộ nhớ đệm trung gian riêng để kiểm tra các câu lệnh đã được chuẩn bị trước các câu lệnh được gửi trước đó. Nó có thể là bạn đang nhìn thấy khi bạn chạy chương trình với Spring. Điều đó có nghĩa là làm một chút truy tìm với hệ thống của bạn để xem liệu bản ghi mysqld chỉ báo cáo các câu lệnh được gửi đi, bất kể nó được xử lý như thế nào.

2

Bạn chỉ nên chuẩn bị câu lệnh của mình một lần, ngoài vòng lặp và sau đó ràng buộc các tham số trong vòng lặp. Đây là lý do tại sao các câu lệnh chuẩn bị có các tham số ràng buộc - vì vậy bạn có thể sử dụng lại câu lệnh đã chuẩn bị.

Hibernate thực hiện chính xác điều này, xử lý tất cả SQL dưới dạng câu lệnh chuẩn bị đằng sau hậu trường, mặc dù bạn rõ ràng có thể lạm dụng điều này nếu bạn sử dụng tham số theo nghĩa đen hơn là kết buộc.

1

Đầu tiên, PreparedStatement của bạn được tạo lại trong vòng lặp, do đó trình điều khiển JDBC được phép loại bỏ dữ liệu đã chuẩn bị. Vì vậy, bạn yêu cầu cho hành vi xấu xí, và vì vậy bạn đã nhận nó.

Và sau đó, PreparedStatement trong MySQL là một chương riêng của mình. Để có bộ nhớ đệm thực, bạn phải yêu cầu nó một cách rõ ràng thông qua một thuộc tính kết nối.

Vì vậy, bạn phải đặt thuộc tính "cachePrepStmts" thành "true" để lưu bộ nhớ đệm trên các câu lệnh đã chuẩn bị. Theo mặc định, thuộc tính đó được đặt thành false.

@ xem hướng dẫn sử dụng MySQL cho phiên bản MySQL của bạn để biết chi tiết

1

Bạn nên chuẩn bị câu lệnh bên ngoài vòng lặp.

Connection conn = DatabaseUtil.getConnection(); 
PreparedStatement stmtUpdate = conn.prepareStatement("UPDATE foo SET bar=? WHERE id = ?"); 
for(int id=0; id<10; id++){ 
    stmtUpdate.setString(1, "baz"); 
    stmtUpdate.setInt(2, id); 
    int rows = stmtUpdate.executeUpdate(); 
    // Clear parameters for reusing the preparedStatement 
    stmtUpdate.clearParameters(); 
} 
conn.close(); 

Tôi không biết về các câu lệnh chuẩn bị bộ nhớ đệm của mysql, nhưng đây là cách mà câu lệnh JDBC chuẩn bị được sử dụng lại.

2

Bạn cũng cần đặt kích thước bộ nhớ cache của câu lệnh trên phiên bản kết nối. Tôi giả sử kích thước bộ nhớ cache mặc định là 0. Do đó không có gì sẽ được lưu trữ.

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