Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

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 !!

docs.sqlalchemy.org

SQLAlchemy 101って本が日本語であれば、1万円でも買います。

追記 2019.12.28

そんなことしなくても、relationship関数のlazyキーワードに、joinedって入れたらそれだけで良いっぽい

# これでJOIN時にFetchしてくれるからN+1にならへん
user = relationship("User", lazy="joined")