Optimize series and presentation unique key grouping to preserve sort order and reduce memory usage
This commit is contained in:
@@ -890,17 +890,28 @@ public sealed class BaseItemRepository
|
||||
/// Applies series grouping at the database level using GROUP BY to avoid loading all episodes into memory.
|
||||
/// This is crucial for TV Shows performance - instead of loading 10,000 episodes and deduplicating in-memory,
|
||||
/// we group by SeriesPresentationUniqueKey at the database level and only load one episode per series.
|
||||
/// IMPORTANT: Gets sorted IDs first to preserve sort order from the ORDER BY clause.
|
||||
/// </summary>
|
||||
private async Task<List<Guid>> ApplySeriesGroupingAtDatabaseLevel(IQueryable<BaseItemEntity> dbQuery, JellyfinDbContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
// Get distinct series presentation keys along with one ID per series
|
||||
// This uses GROUP BY at the database level instead of in-memory DISTINCT
|
||||
var groupedBySeriesIds = await dbQuery
|
||||
.GroupBy(e => e.TvExtras!.SeriesPresentationUniqueKey)
|
||||
.Select(g => g.First().Id)
|
||||
// Get all IDs in sorted order FIRST (preserves the ORDER BY from ApplyOrder)
|
||||
var sortedIds = await dbQuery
|
||||
.Select(e => new { e.Id, SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey })
|
||||
.ToListAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Deduplicate by SeriesPresentationUniqueKey while preserving the sorted order
|
||||
var seenSeries = new HashSet<string>();
|
||||
var groupedBySeriesIds = new List<Guid>();
|
||||
|
||||
foreach (var item in sortedIds)
|
||||
{
|
||||
if (seenSeries.Add(item.SeriesPresentationUniqueKey ?? string.Empty))
|
||||
{
|
||||
groupedBySeriesIds.Add(item.Id);
|
||||
}
|
||||
}
|
||||
|
||||
return groupedBySeriesIds;
|
||||
}
|
||||
|
||||
@@ -908,17 +919,28 @@ public sealed class BaseItemRepository
|
||||
/// Applies presentation unique key grouping at the database level using GROUP BY to avoid loading duplicate items into memory.
|
||||
/// This optimization applies to movies, music videos, and other media types that can have duplicate PresentationUniqueKey values.
|
||||
/// Instead of loading all items and deduplicating in-memory, we group by PresentationUniqueKey at the database level.
|
||||
/// IMPORTANT: Gets sorted IDs first to preserve sort order from the ORDER BY clause.
|
||||
/// </summary>
|
||||
private async Task<List<Guid>> ApplyPresentationUniqueKeyGrouping(IQueryable<BaseItemEntity> dbQuery, JellyfinDbContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
// Get distinct presentation keys along with one ID per unique key
|
||||
// This uses GROUP BY at the database level instead of in-memory DISTINCT
|
||||
var groupedByPresentationKeyIds = await dbQuery
|
||||
.GroupBy(e => e.PresentationUniqueKey)
|
||||
.Select(g => g.First().Id)
|
||||
// Get all IDs in sorted order FIRST (preserves the ORDER BY from ApplyOrder)
|
||||
var sortedIds = await dbQuery
|
||||
.Select(e => new { e.Id, e.PresentationUniqueKey })
|
||||
.ToListAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Deduplicate by PresentationUniqueKey while preserving the sorted order
|
||||
var seenKeys = new HashSet<string>();
|
||||
var groupedByPresentationKeyIds = new List<Guid>();
|
||||
|
||||
foreach (var item in sortedIds)
|
||||
{
|
||||
if (seenKeys.Add(item.PresentationUniqueKey ?? string.Empty))
|
||||
{
|
||||
groupedByPresentationKeyIds.Add(item.Id);
|
||||
}
|
||||
}
|
||||
|
||||
return groupedByPresentationKeyIds;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user