Эти шаги позволили увеличить время загрузки большой базы данных с 12 до 1 минуты.
орое время назад я создал систему, в которой пользователь может определять категории с настраиваемыми полями для некоторых объектов. Затем каждый объект имеет FieldValue в зависимости от его категории. Классы ниже:
public class DbCategory
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public TextDbField MainField { get; set; }
public List<DbField> Fields { get; set; }
}
public class DbObject
{
public int Id { get; set; }
public byte[] Bytes { get; set; }
[Required]
public DbCategory Category { get; set; }
public TextDbFieldValue MainFieldValue { get; set; }
public List<DbFieldValue> FieldsValues { get; set; }
}
public abstract class DbField
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public bool Required { get; set; }
}
public class IntegerDbField : DbField
{
public int? Minimum { get; set; }
public int? Maximum { get; set; }
}
public class FloatDbField : DbField
{
public double? Minimum { get; set; }
public double? Maximum { get; set; }
}
//... few other types
public abstract class DbFieldValue
{
[Key]
public int Id { get; set; }
[Required]
public DbField Field { get; set; }
[JsonIgnore]
public abstract string Value { get; set; }
}
public class IntDbFieldValue : DbFieldValue
{
public int? IntValue { get; set; }
public override string Value
{
get { return IntValue?.ToString(); }
set
{
if (value == null) IntValue = null;
else IntValue = int.Parse(value);
}
}
}// and other FieldValue types
На моем компьютере разработчика (i5, ram 16bg и диск ssd) база данных (в SqlExpress) с 4 категориями, каждая из которых имеет 5-6 полей, 10 тыс. Записей, первый запрос занимает около 15 с. Этот первый запрос
var result = db.Objects
.Include(s => s.Category)
.Include(s => s.Category.MainField)
.Include(s => s.MainFieldValue.Field)
.Include(s => s.FieldsValues.Select(f => f.Field))
.Where(predicate ?? AlwaysTrue)
.ToArray();
Я делаю это, чтобы загрузить все в память. Затем я работаю с кэшированным списком и просто записываю изменения в базу данных. Я делаю это, потому что пользователь может выполнять поиск с фильтром по каждому FieldValue. Запросы к базе данных каждый раз оказывались слишком медленными - однако эта часть работает довольно хорошо.
Проблема возникает позже. Некоторые клиенты определили 6 категорий с 20+ полями в каждой и хранят более 70 тыс. Записей, запуск иногда занимает более 15 минут. После этого нет разницы в скорости между 5k и 50k.
Каждый метод улучшения кода EF Первое время запуска, которое я обнаружил, касается главным образом кэширования создания представления, создания EF и т. Д., Но в этом случае время запуска увеличивается после добавления большего количества записей, а не большего числа типов сущностей.
Я понимаю, что это вызвано сложностью схемы, но есть ли способ ускорить это? К счастью, это служба Windows, поэтому, как только она запускается, она работает неделями, но все же.
Должен ли я сбросить EF для первой загрузки и сделать это на чистом SQL? Должен ли я делать это партиями? Стоит ли менять EF на nHibernate? Или что-то другое? На виртуализированных серверах во время выполнения этой строки эта программа максимально загружает ЦП (не SQL-сервер, а мое приложение).
Я попытался загрузить только объекты, а затем загрузить их свойства позже. Это было немного быстрее (но не заметно) для небольших баз данных, но еще медленнее для больших. Любая помощь приветствуется, даже если ответ «смирись и жди».