SQLAlchemyのLazyLoadとEagerLoad
SQLAlchemyには、カラムを指定できるwith_entitiesという関数がある。
こいつを指定してクエリを組み立てるときは、joinによって指定されたテーブルの中身を、予めもってきてくれるようだ。AlchemyのDebug=Trueで確認した。
db.session.query(Item).join(Category).with_entities( Item.id, Category.name ).all()
だけど、もちろんbackrefの指定にもよるけれど、カラムをな~んにも指定しない場合は、lazyloadになる。該当のプロパティにアクセスされたと同時に、SQLが走る。
rs = db.session.query(Item).join(Category).all() for v in rs: print(rs.category.name) # この度にSQLが走るっぽい
それは困るぜってときは、予めoption関数でjoinした時にもってこいやっていう指定ができる。
rs = db.session.query(Item).options(joinedload(Item.category)).all() for v in rs: print(rs.category.name) # DO NOT N+1 !!
SQLAlchemy 101って本が日本語であれば、1万円でも買います。
追記 2019.12.28
そんなことしなくても、relationship関数のlazyキーワードに、joinedって入れたらそれだけで良いっぽい
# これでJOIN時にFetchしてくれるからN+1にならへん user = relationship("User", lazy="joined")