mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-06-04 06:04:25 -04:00
Minor performance improvements to item saving
This commit is contained in:
parent
46c8a6c1e8
commit
48e1cf9fd7
@ -143,8 +143,17 @@ namespace Emby.Server.Implementations.Data
|
|||||||
public IStatement PrepareStatement(IDatabaseConnection connection, string sql)
|
public IStatement PrepareStatement(IDatabaseConnection connection, string sql)
|
||||||
=> connection.PrepareStatement(sql);
|
=> connection.PrepareStatement(sql);
|
||||||
|
|
||||||
public IEnumerable<IStatement> PrepareAll(IDatabaseConnection connection, IEnumerable<string> sql)
|
public IStatement[] PrepareAll(IDatabaseConnection connection, IReadOnlyList<string> sql)
|
||||||
=> sql.Select(connection.PrepareStatement);
|
{
|
||||||
|
int len = sql.Count;
|
||||||
|
IStatement[] statements = new IStatement[len];
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
statements[i] = connection.PrepareStatement(sql[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
protected bool TableExists(ManagedConnection connection, string name)
|
protected bool TableExists(ManagedConnection connection, string name)
|
||||||
{
|
{
|
||||||
|
@ -560,7 +560,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
{
|
{
|
||||||
SaveItemCommandText,
|
SaveItemCommandText,
|
||||||
"delete from AncestorIds where ItemId=@ItemId"
|
"delete from AncestorIds where ItemId=@ItemId"
|
||||||
}).ToList();
|
});
|
||||||
|
|
||||||
using (var saveItemStatement = statements[0])
|
using (var saveItemStatement = statements[0])
|
||||||
using (var deleteAncestorsStatement = statements[1])
|
using (var deleteAncestorsStatement = statements[1])
|
||||||
@ -2925,7 +2925,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
{
|
{
|
||||||
connection.RunInTransaction(db =>
|
connection.RunInTransaction(db =>
|
||||||
{
|
{
|
||||||
var statements = PrepareAll(db, statementTexts).ToList();
|
var statements = PrepareAll(db, statementTexts);
|
||||||
|
|
||||||
if (!isReturningZeroItems)
|
if (!isReturningZeroItems)
|
||||||
{
|
{
|
||||||
@ -3329,7 +3329,7 @@ namespace Emby.Server.Implementations.Data
|
|||||||
{
|
{
|
||||||
connection.RunInTransaction(db =>
|
connection.RunInTransaction(db =>
|
||||||
{
|
{
|
||||||
var statements = PrepareAll(db, statementTexts).ToList();
|
var statements = PrepareAll(db, statementTexts);
|
||||||
|
|
||||||
if (!isReturningZeroItems)
|
if (!isReturningZeroItems)
|
||||||
{
|
{
|
||||||
@ -3718,26 +3718,31 @@ namespace Emby.Server.Implementations.Data
|
|||||||
statement?.TryBind("@MaxPremiereDate", query.MaxPremiereDate.Value);
|
statement?.TryBind("@MaxPremiereDate", query.MaxPremiereDate.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringBuilder clauseBuilder = new StringBuilder();
|
||||||
|
const string Or = " OR ";
|
||||||
|
|
||||||
var trailerTypes = query.TrailerTypes;
|
var trailerTypes = query.TrailerTypes;
|
||||||
int trailerTypesLen = trailerTypes.Length;
|
int trailerTypesLen = trailerTypes.Length;
|
||||||
if (trailerTypesLen > 0)
|
if (trailerTypesLen > 0)
|
||||||
{
|
{
|
||||||
const string Or = " OR ";
|
clauseBuilder.Append('(');
|
||||||
StringBuilder clause = new StringBuilder("(", trailerTypesLen * 32);
|
|
||||||
for (int i = 0; i < trailerTypesLen; i++)
|
for (int i = 0; i < trailerTypesLen; i++)
|
||||||
{
|
{
|
||||||
var paramName = "@TrailerTypes" + i;
|
var paramName = "@TrailerTypes" + i;
|
||||||
clause.Append("TrailerTypes like ")
|
clauseBuilder.Append("TrailerTypes like ")
|
||||||
.Append(paramName)
|
.Append(paramName)
|
||||||
.Append(Or);
|
.Append(Or);
|
||||||
statement?.TryBind(paramName, "%" + trailerTypes[i] + "%");
|
statement?.TryBind(paramName, "%" + trailerTypes[i] + "%");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove last " OR "
|
// Remove last " OR "
|
||||||
clause.Length -= Or.Length;
|
clauseBuilder.Length -= Or.Length;
|
||||||
clause.Append(')');
|
clauseBuilder.Append(')');
|
||||||
|
|
||||||
whereClauses.Add(clause.ToString());
|
whereClauses.Add(clauseBuilder.ToString());
|
||||||
|
|
||||||
|
clauseBuilder.Length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.IsAiring.HasValue)
|
if (query.IsAiring.HasValue)
|
||||||
@ -3757,23 +3762,35 @@ namespace Emby.Server.Implementations.Data
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.PersonIds.Length > 0)
|
int personIdsLen = query.PersonIds.Length;
|
||||||
|
if (personIdsLen > 0)
|
||||||
{
|
{
|
||||||
// TODO: Should this query with CleanName ?
|
// TODO: Should this query with CleanName ?
|
||||||
|
|
||||||
var clauses = new List<string>();
|
clauseBuilder.Append('(');
|
||||||
var index = 0;
|
|
||||||
foreach (var personId in query.PersonIds)
|
|
||||||
{
|
|
||||||
var paramName = "@PersonId" + index;
|
|
||||||
|
|
||||||
clauses.Add("(guid in (select itemid from People where Name = (select Name from TypedBaseItems where guid=" + paramName + ")))");
|
Span<byte> idBytes = stackalloc byte[16];
|
||||||
statement?.TryBind(paramName, personId.ToByteArray());
|
for (int i = 0; i < personIdsLen; i++)
|
||||||
index++;
|
{
|
||||||
|
string paramName = "@PersonId" + i;
|
||||||
|
clauseBuilder.Append("(guid in (select itemid from People where Name = (select Name from TypedBaseItems where guid=")
|
||||||
|
.Append(paramName)
|
||||||
|
.Append("))) OR ");
|
||||||
|
|
||||||
|
if (statement != null)
|
||||||
|
{
|
||||||
|
query.PersonIds[i].TryWriteBytes(idBytes);
|
||||||
|
statement.TryBind(paramName, idBytes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var clause = "(" + string.Join(" OR ", clauses) + ")";
|
// Remove last " OR "
|
||||||
whereClauses.Add(clause);
|
clauseBuilder.Length -= Or.Length;
|
||||||
|
clauseBuilder.Append(')');
|
||||||
|
|
||||||
|
whereClauses.Add(clauseBuilder.ToString());
|
||||||
|
|
||||||
|
clauseBuilder.Length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(query.Person))
|
if (!string.IsNullOrWhiteSpace(query.Person))
|
||||||
@ -5149,7 +5166,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||||||
|
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
|
|
||||||
var itemIdBlob = itemId.ToByteArray();
|
Span<byte> itemIdBlob = stackalloc byte[16]
|
||||||
|
itemId.TryWriteBytes(itemIdBlob);
|
||||||
|
|
||||||
// First delete
|
// First delete
|
||||||
deleteAncestorsStatement.Reset();
|
deleteAncestorsStatement.Reset();
|
||||||
@ -5165,17 +5183,15 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||||||
|
|
||||||
for (var i = 0; i < ancestorIds.Count; i++)
|
for (var i = 0; i < ancestorIds.Count; i++)
|
||||||
{
|
{
|
||||||
if (i > 0)
|
|
||||||
{
|
|
||||||
insertText.Append(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
insertText.AppendFormat(
|
insertText.AppendFormat(
|
||||||
CultureInfo.InvariantCulture,
|
CultureInfo.InvariantCulture,
|
||||||
"(@ItemId, @AncestorId{0}, @AncestorIdText{0})",
|
"(@ItemId, @AncestorId{0}, @AncestorIdText{0}),",
|
||||||
i.ToString(CultureInfo.InvariantCulture));
|
i.ToString(CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove last ,
|
||||||
|
insertText.Length--;
|
||||||
|
|
||||||
using (var statement = PrepareStatement(db, insertText.ToString()))
|
using (var statement = PrepareStatement(db, insertText.ToString()))
|
||||||
{
|
{
|
||||||
statement.TryBind("@ItemId", itemIdBlob);
|
statement.TryBind("@ItemId", itemIdBlob);
|
||||||
@ -5185,8 +5201,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||||||
var index = i.ToString(CultureInfo.InvariantCulture);
|
var index = i.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
var ancestorId = ancestorIds[i];
|
var ancestorId = ancestorIds[i];
|
||||||
|
ancestorId.TryWriteBytes(itemIdBlob);
|
||||||
|
|
||||||
statement.TryBind("@AncestorId" + index, ancestorId.ToByteArray());
|
statement.TryBind("@AncestorId" + index, itemIdBlob);
|
||||||
statement.TryBind("@AncestorIdText" + index, ancestorId.ToString("N", CultureInfo.InvariantCulture));
|
statement.TryBind("@AncestorIdText" + index, ancestorId.ToString("N", CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5466,7 +5483,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
|
|||||||
connection.RunInTransaction(
|
connection.RunInTransaction(
|
||||||
db =>
|
db =>
|
||||||
{
|
{
|
||||||
var statements = PrepareAll(db, statementTexts).ToList();
|
var statements = PrepareAll(db, statementTexts);
|
||||||
|
|
||||||
if (!isReturningZeroItems)
|
if (!isReturningZeroItems)
|
||||||
{
|
{
|
||||||
|
@ -513,10 +513,11 @@ namespace Emby.Server.Implementations.Library
|
|||||||
throw new ArgumentNullException(nameof(type));
|
throw new ArgumentNullException(nameof(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key.StartsWith(_configurationManager.ApplicationPaths.ProgramDataPath, StringComparison.Ordinal))
|
string programDataPath = _configurationManager.ApplicationPaths.ProgramDataPath;
|
||||||
|
if (key.StartsWith(programDataPath, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
// Try to normalize paths located underneath program-data in an attempt to make them more portable
|
// Try to normalize paths located underneath program-data in an attempt to make them more portable
|
||||||
key = key.Substring(_configurationManager.ApplicationPaths.ProgramDataPath.Length)
|
key = key.Substring(programDataPath.Length)
|
||||||
.TrimStart('/', '\\')
|
.TrimStart('/', '\\')
|
||||||
.Replace('/', '\\');
|
.Replace('/', '\\');
|
||||||
}
|
}
|
||||||
@ -871,17 +872,17 @@ namespace Emby.Server.Implementations.Library
|
|||||||
|
|
||||||
public Guid GetStudioId(string name)
|
public Guid GetStudioId(string name)
|
||||||
{
|
{
|
||||||
return GetItemByNameId<Studio>(Studio.GetPath, name);
|
return GetItemByNameId<Studio>(Studio.GetPath(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid GetGenreId(string name)
|
public Guid GetGenreId(string name)
|
||||||
{
|
{
|
||||||
return GetItemByNameId<Genre>(Genre.GetPath, name);
|
return GetItemByNameId<Genre>(Genre.GetPath(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Guid GetMusicGenreId(string name)
|
public Guid GetMusicGenreId(string name)
|
||||||
{
|
{
|
||||||
return GetItemByNameId<MusicGenre>(MusicGenre.GetPath, name);
|
return GetItemByNameId<MusicGenre>(MusicGenre.GetPath(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -943,7 +944,7 @@ namespace Emby.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
var existing = GetItemList(new InternalItemsQuery
|
var existing = GetItemList(new InternalItemsQuery
|
||||||
{
|
{
|
||||||
IncludeItemTypes = new[] { typeof(T).Name },
|
IncludeItemTypes = new[] { nameof(MusicArtist) },
|
||||||
Name = name,
|
Name = name,
|
||||||
DtoOptions = options
|
DtoOptions = options
|
||||||
}).Cast<MusicArtist>()
|
}).Cast<MusicArtist>()
|
||||||
@ -957,13 +958,11 @@ namespace Emby.Server.Implementations.Library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = GetItemByNameId<T>(getPathFn, name);
|
var path = getPathFn(name);
|
||||||
|
var id = GetItemByNameId<T>(path);
|
||||||
|
|
||||||
var item = GetItemById(id) as T;
|
if (GetItemById(id) is T item)
|
||||||
|
|
||||||
if (item == null)
|
|
||||||
{
|
{
|
||||||
var path = getPathFn(name);
|
|
||||||
item = new T
|
item = new T
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
@ -974,15 +973,16 @@ namespace Emby.Server.Implementations.Library
|
|||||||
};
|
};
|
||||||
|
|
||||||
CreateItem(item, null);
|
CreateItem(item, null);
|
||||||
|
|
||||||
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
return item;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Guid GetItemByNameId<T>(Func<string, string> getPathFn, string name)
|
private Guid GetItemByNameId<T>(string path)
|
||||||
where T : BaseItem, new()
|
where T : BaseItem, new()
|
||||||
{
|
{
|
||||||
var path = getPathFn(name);
|
|
||||||
var forceCaseInsensitiveId = _configurationManager.Configuration.EnableNormalizedItemByNameIds;
|
var forceCaseInsensitiveId = _configurationManager.Configuration.EnableNormalizedItemByNameIds;
|
||||||
return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId);
|
return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId);
|
||||||
}
|
}
|
||||||
@ -1805,21 +1805,18 @@ namespace Emby.Server.Implementations.Library
|
|||||||
/// <param name="items">The items.</param>
|
/// <param name="items">The items.</param>
|
||||||
/// <param name="parent">The parent item.</param>
|
/// <param name="parent">The parent item.</param>
|
||||||
/// <param name="cancellationToken">The cancellation token.</param>
|
/// <param name="cancellationToken">The cancellation token.</param>
|
||||||
public void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken)
|
public void CreateItems(IReadOnlyList<BaseItem> items, BaseItem parent, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// Don't iterate multiple times
|
_itemRepository.SaveItems(items, cancellationToken);
|
||||||
var itemsList = items.ToList();
|
|
||||||
|
|
||||||
_itemRepository.SaveItems(itemsList, cancellationToken);
|
foreach (var item in items)
|
||||||
|
|
||||||
foreach (var item in itemsList)
|
|
||||||
{
|
{
|
||||||
RegisterItem(item);
|
RegisterItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ItemAdded != null)
|
if (ItemAdded != null)
|
||||||
{
|
{
|
||||||
foreach (var item in itemsList)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
// With the live tv guide this just creates too much noise
|
// With the live tv guide this just creates too much noise
|
||||||
if (item.SourceType != SourceType.Library)
|
if (item.SourceType != SourceType.Library)
|
||||||
|
@ -257,8 +257,7 @@ namespace Emby.Server.Implementations.Security
|
|||||||
connection.RunInTransaction(
|
connection.RunInTransaction(
|
||||||
db =>
|
db =>
|
||||||
{
|
{
|
||||||
var statements = PrepareAll(db, statementTexts)
|
var statements = PrepareAll(db, statementTexts);
|
||||||
.ToList();
|
|
||||||
|
|
||||||
using (var statement = statements[0])
|
using (var statement = statements[0])
|
||||||
{
|
{
|
||||||
@ -282,7 +281,7 @@ namespace Emby.Server.Implementations.Security
|
|||||||
ReadTransactionMode);
|
ReadTransactionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Items = list.ToArray();
|
result.Items = list;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ namespace MediaBrowser.Controller.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates the items.
|
/// Creates the items.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void CreateItems(IEnumerable<BaseItem> items, BaseItem parent, CancellationToken cancellationToken);
|
void CreateItems(IReadOnlyList<BaseItem> items, BaseItem parent, CancellationToken cancellationToken);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the item.
|
/// Updates the item.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user