参考:
http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#eager-loading
预先加载
前面的代码,因为是lazy load,当我们调用User.addresses 时,sqlalchemy才会发出sql语句去取addresses,
比如:
query = session.query(User).all()
for user in query:
print(user.addresses)
如果有10个用户,for循环10次,就会发10个取user中address信息的sql请求,这样很没有效率。
可以使用预先加载,在一个sql请求中吧User.addresses 都取出来。
subquery 加载
看例子:
users = session.query(User).options(subqueryload(User.addresses)).all()
发出的sql
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password
FROM users;
SELECT addresses.id AS addresses_id, addresses.email_address AS addresses_email_address, addresses.user_id AS addresses_user_id, anon_1.users_id AS anon_1_users_id
FROM (SELECT users.id AS users_id
FROM users) AS anon_1 JOIN addresses ON anon_1.users_id = addresses.user_id ORDER BY anon_1.users_id, addresses.id;
当取出users时,会发出2个sql,第一个sql是取出所有user的基本信息,第二个sql时取出所有user的address信息。
joinedload 加载
joinedload 加载会使用 LEFT OUTER JOIN 来加载信息
users = session.query(User).options(joinedload(User.addresses)).all()
SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password, addresses_1.id AS addresses_1_id, addresses_1.email_address AS addresses_1_email_address, addresses_1.user_id AS addresses_1_user_id
FROM users LEFT OUTER JOIN addresses AS addresses_1 ON users.id = addr;
明确的使用join
当已经明确大join了User.addresses 后,可以使用contains_eager来加载address的信息。
users = session.query(User).join(User.addresses).options(contains_eager(User.addresses)).all()