Cả hai chiến lược tải có vấn đề đều nêu ra các ngoại lệ nếu bạn cố gắng sử dụng chúng với yield_per
, vì vậy bạn không thực sự phải lo lắng quá nhiều.
Tôi tin vấn đề duy nhất với subqueryload
là việc tải hàng loạt truy vấn thứ hai chưa được triển khai (chưa). Sẽ không có gì sai về mặt ngữ nghĩa, nhưng nếu bạn đang sử dụng yield_per
, bạn có thể có một lý do thực sự chính đáng để không muốn tải tất cả các kết quả cùng một lúc. Vì vậy, SQLAlchemy lịch sự từ chối đi ngược lại mong muốn của bạn.
joinedload
là một chút tinh tế hơn. Nó chỉ bị cấm trong trường hợp tập hợp, trong đó hàng chính có thể có nhiều hàng được liên kết. Giả sử truy vấn của bạn tạo ra kết quả thô như thế này, trong đó A và B là khóa chính từ các bảng khác nhau:
A | B
---+---
1 | 1
1 | 2
1 | 3
1 | 4
2 | 5
2 | 6
Bây giờ bạn tìm nạp những thứ này bằng yield_per(3)
. Vấn đề là SQLAlchemy chỉ có thể giới hạn số lượng nó tìm nạp theo hàng , nhưng nó phải trả về đối tượng . Ở đây, SQLAlchemy chỉ nhìn thấy ba hàng đầu tiên, vì vậy nó tạo ra một A
đối tượng có phím 1 và ba B
trẻ em:1, 2 và 3.
Khi tải đợt tiếp theo, nó muốn tạo một A
mới đối tượng có khóa 1 ... à, nhưng nó đã có một trong các khóa đó rồi nên không cần tạo lại. B
bổ sung , 4, bị mất. (Vì vậy, không, thậm chí đọc các bộ sưu tập đã kết hợp với yield_per
không an toàn - nhiều phần dữ liệu của bạn có thể bị thiếu.)
Bạn có thể nói "tốt, chỉ cần tiếp tục đọc các hàng cho đến khi bạn có một đối tượng đầy đủ" - nhưng điều gì sẽ xảy ra nếu điều đó A
có một trăm trẻ em? Hay một triệu? SQLAlchemy không thể đảm bảo một cách hợp lý rằng nó có thể làm những gì bạn đã yêu cầu và tạo ra kết quả chính xác, vì vậy nó từ chối thử.
Hãy nhớ rằng DBAPI được thiết kế để bất kỳ cơ sở dữ liệu có thể được sử dụng với cùng một API, ngay cả khi cơ sở dữ liệu đó không hỗ trợ tất cả các tính năng của DBAPI. Hãy xem xét rằng DBAPI được thiết kế xung quanh con trỏ, nhưng MySQL không thực sự có con trỏ! Thay vào đó, các bộ điều hợp DBAPI cho MySQL phải giả mạo chúng.
Vì vậy, trong khi cursor.fetchmany(100)
sẽ làm việc , bạn có thể xem từ MySQLdb
mã nguồn
rằng nó không tìm nạp một cách lười biếng từ máy chủ; nó tìm nạp mọi thứ vào một danh sách lớn, sau đó trả về một lát khi bạn gọi fetchmany
.
Cái gì psycopg2
hỗ trợ là phát trực tuyến thực sự, nơi kết quả được ghi nhớ liên tục trên máy chủ và quy trình Python của bạn chỉ thấy một vài trong số chúng cùng một lúc.
Bạn vẫn có thể sử dụng yield_per
với MySQLdb
, hoặc bất kỳ DBAPI nào khác; đó là toàn bộ điểm của thiết kế DBAPI. Bạn sẽ phải trả chi phí bộ nhớ cho tất cả các hàng thô bị ẩn trong DBAPI (là các bộ giá trị, khá rẻ), nhưng bạn sẽ không cũng không phải trả tiền cho tất cả các đối tượng ORM cùng một lúc.