diff options
| author | Shadowghost <Ghost_of_Stone@web.de> | 2026-02-07 00:56:55 +0100 |
|---|---|---|
| committer | Shadowghost <Ghost_of_Stone@web.de> | 2026-02-07 01:38:06 +0100 |
| commit | 268d88a5fb8f0f71c96ba5abcef250d1f7e049ff (patch) | |
| tree | dbca9e0725ed368f8621901b96a1f1a5846c500a /Emby.Server.Implementations | |
| parent | 8ddc35a1ced32b40ef2ee333f2adcc57f3725811 (diff) | |
Optimize Collection Grouping, NextUp and Latest queries
Diffstat (limited to 'Emby.Server.Implementations')
| -rw-r--r-- | Emby.Server.Implementations/Dto/DtoService.cs | 24 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Library/LibraryManager.cs | 6 |
2 files changed, 25 insertions, 5 deletions
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index e34e752da3..626f4ed0cd 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -185,10 +185,23 @@ namespace Emby.Server.Implementations.Dto } } + // Batch-fetch played/total counts for all folders to avoid N+1 queries + Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null; + if (user is not null && options.EnableUserData) + { + var folderIds = accessibleItems.OfType<Folder>() + .Where(f => f.SupportsUserDataFromChildren && (f.SupportsPlayedStatus || options.ContainsField(ItemFields.RecursiveItemCount))) + .Select(f => f.Id).ToList(); + if (folderIds.Count > 0) + { + playedCountBatch = _libraryManager.GetPlayedAndTotalCountBatch(folderIds, user); + } + } + for (int index = 0; index < accessibleItems.Count; index++) { var item = accessibleItems[index]; - var dto = GetBaseItemDtoInternal(item, options, user, owner, userDataBatch?.GetValueOrDefault(item.Id), allCollectionFolders, childCountBatch); + var dto = GetBaseItemDtoInternal(item, options, user, owner, userDataBatch?.GetValueOrDefault(item.Id), allCollectionFolders, childCountBatch, playedCountBatch); if (item is LiveTvChannel tvChannel) { @@ -240,7 +253,7 @@ namespace Emby.Server.Implementations.Dto return dto; } - private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null, UserItemData? userData = null, List<Folder>? allCollectionFolders = null, Dictionary<Guid, int>? childCountBatch = null) + private BaseItemDto GetBaseItemDtoInternal(BaseItem item, DtoOptions options, User? user = null, BaseItem? owner = null, UserItemData? userData = null, List<Folder>? allCollectionFolders = null, Dictionary<Guid, int>? childCountBatch = null, Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null) { var dto = new BaseItemDto { @@ -277,7 +290,7 @@ namespace Emby.Server.Implementations.Dto if (user is not null) { - AttachUserSpecificInfo(dto, item, user, options, userData, childCountBatch); + AttachUserSpecificInfo(dto, item, user, options, userData, childCountBatch, playedCountBatch); } if (item is IHasMediaSources @@ -485,7 +498,7 @@ namespace Emby.Server.Implementations.Dto /// <summary> /// Attaches the user specific info. /// </summary> - private void AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, DtoOptions options, UserItemData? userData = null, Dictionary<Guid, int>? childCountBatch = null) + private void AttachUserSpecificInfo(BaseItemDto dto, BaseItem item, User user, DtoOptions options, UserItemData? userData = null, Dictionary<Guid, int>? childCountBatch = null, Dictionary<Guid, (int Played, int Total)>? playedCountBatch = null) { if (item.IsFolder) { @@ -497,7 +510,8 @@ namespace Emby.Server.Implementations.Dto { // Use pre-fetched user data dto.UserData = GetUserItemDataDto(userData, item.Id); - item.FillUserDataDtoValues(dto.UserData, userData, dto, user, options); + (int Played, int Total)? precomputed = playedCountBatch is not null && playedCountBatch.TryGetValue(item.Id, out var counts) ? counts : null; + item.FillUserDataDtoValues(dto.UserData, userData, dto, user, options, precomputed); } else { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 38aec6d491..29eda7d8b1 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1515,6 +1515,12 @@ namespace Emby.Server.Implementations.Library return _itemRepository.GetChildCountBatch(parentIds, userId); } + /// <inheritdoc/> + public Dictionary<Guid, (int Played, int Total)> GetPlayedAndTotalCountBatch(IReadOnlyList<Guid> folderIds, User user) + { + return _itemRepository.GetPlayedAndTotalCountBatch(folderIds, user); + } + public IReadOnlyList<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents) { SetTopParentIdsOrAncestors(query, parents); |
