File: app/api/channels.py
Lines: ~38-42 (in list_channels) & ~132-140 (in subscribe)
Description:
Multiple endpoints in the Channels router execute database queries in a loop, resulting in an N+1 query performance issue:
- In
list_channels(), a SELECT count() on the Video table is executed for every single channel in the database sequentially.
- In
subscribe(), the application iterates through all existing Video records associated with the newly subscribed channel, running a SELECT UserVideoRef query inside the for video in existing_videos loop.
- In
list_channel_videos(), a similar loop queries UserVideoRef sequentially for every video.
Impact:
For channels with thousands of videos, or an instance with hundreds of channels, these endpoints will take several seconds to resolve or potentially time out, severely degrading database and API performance.
Suggested Fix:
- Use SQLAlchemy
GROUP_BY count or a subquery to fetch video counts for all channels in a single batched query.
- Use an
IN clause (Video.id.in_([...])) to fetch all associated UserVideoRef objects up-front for the batch of videos.
File:
app/api/channels.pyLines: ~38-42 (in
list_channels) & ~132-140 (insubscribe)Description:
Multiple endpoints in the Channels router execute database queries in a loop, resulting in an
N+1query performance issue:list_channels(), aSELECT count()on theVideotable is executed for every single channel in the database sequentially.subscribe(), the application iterates through all existingVideorecords associated with the newly subscribed channel, running aSELECT UserVideoRefquery inside thefor video in existing_videosloop.list_channel_videos(), a similar loop queriesUserVideoRefsequentially for every video.Impact:
For channels with thousands of videos, or an instance with hundreds of channels, these endpoints will take several seconds to resolve or potentially time out, severely degrading database and API performance.
Suggested Fix:
GROUP_BYcount or a subquery to fetch video counts for all channels in a single batched query.INclause (Video.id.in_([...])) to fetch all associatedUserVideoRefobjects up-front for the batch of videos.