Truy vấn dữ liệu trong python
Đã đăng vào thg 11 28, 2015 5:39 CH 5 phút đọc Khi chúng ta truy xuất nhiều bản ghi trong cơ sở dữ liệu cùng 1 lúc sẽ sảy ra một số vấn đề sau. ** I. Hết bộ nhớ**1. Vấn đềMột câu truy vấn có thể trả về một lượng dữ liệu khổng lồ. Ví dụ câu truy vấn SELECT * FROM users có thể trả về hơn chục triệu bản ghi ở các ứng dụng lớn. Trong điều kiện bình thường, có lẽ lượng bản ghi lớn như vậy sẽ khiến cho chương trình của chúng ta sử dụng hết bộ nhớ và bị buộc phải chấm dứt giữa chừng, cho dù chúng ta có sử dụng fetchone, fetchmany hay fetchall để lấy dữ liệu. Lý do là phần giao tiếp giữa Python và MySQL mặc định sẽ lấy tất cả các bản ghi của câu truy vấn về trước, chứa chúng trong bộ nhớ, rồi sau đó trả về cho Python một bản ghi, nhiều bản ghi, hay tất cả các bản ghi đó tùy thuộc vào hàm nào được gọi. Điều này cũng dễ hiểu vì giao thức mạng của MySQL là mô hình yêu cầu/đáp trả (request/response). Một truy vấn là một yêu cầu. Và các bản ghi của truy vấn đó là một đáp trả. Cho nên trình điều khiển (driver) cần phải đọc hết toàn bộ đáp trả để kết thúc chu trình yêu cầu/đáp trả trước khi trả lời các lời gọi hàm fetchone, fetchmany hay fetchall. Nói một cách khác, các hàm fetchone hay fetchmany trả về kết quả đã có trong bộ nhớ. Đó cũng chính là lý do vì sao chúng ta có thể gọi fetchone hay fetchmany nhiều lần. Các hàm này không tạo một chu trình yêu cầu/đáp trả mới mà chỉ đơn giản là tiếp tục trả về các bản ghi đã chứa trong bộ nhớ. 2. Cách khắc phụcCách khắc phục là sử dụng SSCursor khi tạo con trỏ từ kết nối MySQL. Lớp SSCursor nằm trong mô-đun MySQLdb.
Sau đó khi gọi fetchone hoặc fetchmany thì trình điều khiển sẽ không đọc toàn bộ đáp trả vào bộ nhớ nữa mà sẽ chỉ đọc vừa đủ để trả về bấy nhiêu bản ghi cho ta. 3. Lưu ý
Vì SSCursor không giữ kết quả trong bộ nhớ nên ta sẽ không thể di chuyển con trỏ tới, hoặc lùi để truy xuất bản ghi ta cần. Điều duy nhất chúng ta có thể làm với SSCursor là đọc tuần tự tất cả các bản ghi. II. Hết giờ (timeout)1. Vấn đềVới SSCursor ta có thể sẽ viết mã như sau để đọc lần lượt các bản ghi trong bộ nhớ đệm:
Đoạn mã này đôi khi sẽ gây ra lỗi đệm Lost connection to MySQL server during query. Lý do là việc xử lý từng bản ghi sẽ rất tốn thời gian, và ta sẽ không thể đọc đáp trả đủ nhanh, khiến cho máy chủ MySQL phải hoãn việc gửi tiếp các bản ghi về cho ta. Máy chủ MySQL chỉ có thể hoãn việc gửi thông tin trong một thời gian ngắn. Quá thời gian này, máy chủ sẽ tự ngắt kết nối. 2. Cách khắc phụcTốt nhất là chúng ta sử dụng SSCursor để đọc tất cả các bản ghi từ máy chủ ở xa và ghi chúng vào một tập tin trên máy hiện tại. Sau đó ta đọc lại từ tập tin này và xử lý từng bản ghi đã lưu. Khi làm như vậy, chúng ta tránh được lỗi hết bộ nhớ đã đề cập ở trên, và hy vọng rằng việc ghi bản tin ra dĩa xảy ra đủ nhanh để ta có thể đọc bản ghi khác gần như ngay lập tức, tránh được lỗi hết giờ. _Note _: Hiện nay một số Frameworkày sử dụng ORM như Django hỗ trợ rất tốt vấn đề truy vấn này. Nên gần như lập trình viên ko còn phải qúa bận tâm. Nhưng nếu bạn thực sự muốn cấu hình Project của mình theo 1 cách riêng biệt thì hãy bắt tay vào học từ những điều cơ bản nhất. All rights reserved Trong các bài trước, chúng ta thấy rằng số lượng các bản ghi của cơ sở dữ liệu được đề cập trong các ví dụ được giới hạn ở mức tương đối ít, và các dữ liệu được tổ chức theo kiểu khá đơn giản. Ở bài này chúng ta sẽ cùng tìm hiểu về cách để ghi (write) và tìm nạp (fetch) dữ liệu lớn từ cơ sở dữ liệu bằng cách sử dụng module SQLite3. Cách tìm nạp dữ liệu đơn giản nhất chính là thực thi câu truy vấn bằng hàm execute() và sau đó sử dụng hàm fetchall(). Điều này đã được đề cập trong bài “Thao tác với cơ sở dữ liệu trong Python – Phần 1”.
+ Cú pháp:
+ Ví dụ:
+ Kết quả in ra là:
+ Lưu ý: Đoạn code ví dụ này có thể sẽ không hoạt động trên các trình thông dịch trực tuyến (online interpreters), do gặp vấn đề về sự cho phép các đặc quyền để tạo và ghi vào cơ sở dữ liệu.
+ Ví dụ:
+ Kết quả in ra là:
+ Việc sử dụng hàm executemany() có thể làm cho đoạn code sau hoạt động:
+ Kết quả in ra là:
+ Ví dụ:
+ Kết quả in ra là:
+ Lưu ý: Đoạn code ví dụ này có thể sẽ không hoạt động trên các trình thông dịch trực tuyến (online interpreters), do gặp vấn đề về sự cho phép các đặc quyền để tạo và ghi vào cơ sở dữ liệu. Nguồn và Tài liệu tiếng anh tham khảo:
Tài liệu từ cafedev:
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng! Đăng ký kênh youtube để ủng hộ Cafedev nha các bạn, Thanks you! |