#c# #search
#c# #Поиск
Вопрос:
У меня есть консольное приложение C #, которое сохраняет данные в таблицах 2 db, таблице сущностей и таблице отношений. Каждая сущность имеет отношения «Многие ко многим» с другими сущностями. В таблице отношений хранится пара идентификаторов, которые, в свою очередь, являются первичным ключом таблицы сущностей.
Данные в обеих таблицах должны быть уникальными. Первоначально я проверил это, прежде чем вставлять новые индивидуальные записи в хранимую процедуру базы данных. Когда числа начинают увеличиваться в обеих таблицах (> 50 кб в таблице сущностей и> 100 кб в таблице отношений) Я заметил, что производительность действительно начала падать.
Я понял, что обращение к БД для выполнения проверок на наличие дубликатов записей значительно повышает производительность из-за дополнительных затрат на ввод-вывод, поэтому я переработал свой код, чтобы сначала прочитать обе таблицы в памяти, а затем выполнить проверки там. вместо этого. Это повысило производительность, хотя я подозреваю, что она все еще может быть не идеальной. Вот как это выглядит сейчас:
private IEnumerable<long> _existingUsers = dao.GetUserIds();
private IEnumerable<Relations> _existingRelations = dao.GetRelations();
if (!_existingUsers.Contains(inputModel.ID))
{
// db code to create the new Entity record
}
Relations rel = new Relations { Node = inputModel.Node, Follower = inputModel.ID };
if (!_existingRelations.Contains(rel))
{
// db code to create the new Relation entry
}
Класс отношений:
public class Relations : IEquatable<Relations>
{
public long Node { get; set; }
public long Follower { get; set; }
public bool Equals(Relations other)
{
return (other.Node == this.Node) amp;amp; (other.Follower == this.Follower);
}
}
Через отладчик я вижу, что большая часть времени теперь тратится на определение того, содержит ли коллекция _existingRelations в памяти экземпляр «rel». Это, в свою очередь, многократно вызывает метод Equals класса Relations .
Я подозреваю, что может быть более эффективный способ сделать это, но я не знаю, что это такое.
Комментарии:
1. Отсортирована ли коллекция по ключу? Если да: бинарный поиск. Это словарь / хэш? Отлично: используйте это!
2. @MarcGravell Обе коллекции являются списком<T>
3. и снова: отсортирован ли он? Наличие списка ничего не говорит мне о том, отсортирован ли он
Ответ №1:
Это зависит от конкретной реализации IEnumerable .
Это то, что происходит при вызове contains
списка. Поиск в списке всегда перебирал весь список, чтобы найти элемент. Таким образом, нет более быстрого способа его найти.
Если вы вызовете это: https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.hashset-1.contains?view=netcore-3.1 тогда вы получите O(1)
, как и в случае HashSet
со словарями и.
С другой стороны, hashset не упорядочен.
Комментарии:
1. Обе коллекции реализованы в виде списка<T> . Итак, если я вместо этого использую HashSet<T>, это будет намного быстрее?
2. Хорошо, это снизило мой тестовый пример с 129 до> 86 секунд. Хороший материал, спасибо