-
Notifications
You must be signed in to change notification settings - Fork 0
perf(#124): クエリ最適化 (joinedload + 認可統合 + pool 設定見直し) #143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,6 +43,7 @@ | |
| ], | ||
| "cSpell.words": [ | ||
| "embla", | ||
| "joinedload", | ||
| "shadcn", | ||
| "shinkansen" | ||
| ], | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,23 @@ | ||
| from sqlalchemy import select | ||
| from sqlalchemy.ext.asyncio import AsyncSession | ||
| from sqlalchemy.orm import selectinload | ||
| from sqlalchemy.orm import joinedload | ||
|
|
||
| from app.models import Block, Page, Trip | ||
| from app.schemas.trip import TripCreateIn, TripUpdate | ||
|
|
||
|
|
||
| def _trip_with_relations(): | ||
| """Trip → Pages → Blocks → Locations を 1 クエリの LEFT JOIN で取得する。 | ||
|
|
||
| 1-to-many を joinedload で連鎖させるため重複行が発生する。呼び出し側で | ||
| `result.unique()` を挟むこと。クエリ数を 4 から 1 に減らす目的。 | ||
| """ | ||
| return select(Trip).options( | ||
| selectinload(Trip.pages).selectinload(Page.blocks).options( | ||
| selectinload(Block.location), | ||
| selectinload(Block.destination_location), | ||
| joinedload(Trip.pages) | ||
| .joinedload(Page.blocks) | ||
| .options( | ||
| joinedload(Block.location), | ||
| joinedload(Block.destination_location), | ||
| ) | ||
| ) | ||
|
|
||
|
|
@@ -43,8 +50,8 @@ async def find_trips(db: AsyncSession) -> list[Trip]: | |
| Returns: | ||
| list[Trip]: すべての旅行プラン | ||
| """ | ||
| result = await db.execute(_trip_with_relations()) | ||
| return list(result.scalars().all()) | ||
| result = await db.execute(_trip_with_relations().order_by(Trip.id)) | ||
| return list(result.unique().scalars().all()) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 概要
詳細
対策案一覧取得用の # 例: リレーションを含めないシンプルな一覧取得
async def find_trips(db: AsyncSession) -> list[Trip]:
result = await db.execute(select(Trip))
return list(result.scalars().all())References
|
||
|
|
||
|
|
||
| async def get_trip(db: AsyncSession, trip_id: int) -> Trip | None: | ||
|
|
@@ -59,7 +66,7 @@ async def get_trip(db: AsyncSession, trip_id: int) -> Trip | None: | |
| Trip | None: 特定の旅行プラン、見つからない場合はNone | ||
| """ | ||
| result = await db.execute(_trip_with_relations().where(Trip.id == trip_id)) | ||
| return result.scalar_one_or_none() | ||
| return result.unique().scalar_one_or_none() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 概要
詳細旅行プランの更新( 対策案
async def update_trip(db: AsyncSession, trip_id: int, trip: TripUpdate) -> Trip | None:
# 関連データを含まないシンプルな取得
stmt = select(Trip).where(Trip.id == trip_id)
result = await db.execute(stmt)
db_trip = result.scalar_one_or_none()
if db_trip:
for key, value in trip.model_dump().items():
setattr(db_trip, key, value)
await db.commit()
return db_tripReferences
|
||
|
|
||
|
|
||
| async def get_trip_by_url_id(db: AsyncSession, url_id: str) -> Trip | None: | ||
|
|
@@ -74,7 +81,7 @@ async def get_trip_by_url_id(db: AsyncSession, url_id: str) -> Trip | None: | |
| Trip | None: 特定の旅行プラン、見つからない場合はNone | ||
| """ | ||
| result = await db.execute(_trip_with_relations().where(Trip.url_id == url_id)) | ||
| return result.scalar_one_or_none() | ||
| return result.unique().scalar_one_or_none() | ||
|
|
||
|
|
||
| async def update_trip(db: AsyncSession, trip_id: int, trip: TripUpdate) -> Trip | None: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
概要
get_pageは_page_with_relations()を使用して常にblocksやlocationsをjoinedloadしていますが、これがupdate_page(ページの更新処理)内でも呼び出されているため、更新時にも不要な関連データの取得(LEFT JOIN)が走ってしまいます。詳細
ページの更新処理(
update_page)では、通常Pageのスカラー値(titleやdate)のみを更新するため、関連データをロードする必要はありません。対策案
update_page内では、関連データを含まないシンプルなクエリでPageを取得するように変更することを推奨します。References