Я использую Entity Framework Core. Используя этот код, получение 2000 записей занимает более 1 минуты. Пожалуйста, помогите мне найти данные за считанные секунды.
var incomingEmails = acompDbContext.IncomingEmails.AsNoTracking().Where(ie => ie.ReceiverRuc == req.ReceiverRuc)
.Select(ie => new IncomingEmail
{
// Select only necessary properties
IncomingEmailId = ie.IncomingEmailId,
IdStatusMail = ie.IdStatusMail,
MessageId = ie.MessageId,
From = ie.From,
To = ie.To,
Subject = ie.Subject,
Body = ie.Body,
AttachmentName = ie.AttachmentName,
Attachment = ie.Attachment,
AttachmentType = ie.AttachmentType,
AttachmentId = ie.AttachmentId,
EmitterRuc = ie.EmitterRuc,
EmitterBusinessName = ie.EmitterBusinessName,
ReceiverRuc = ie.ReceiverRuc,
Date = ie.Date,
Valid = ie.Valid
}).ToListAsync();
Я пытался уменьшить данные, но мне нужны все 2000 записей.
@Charlieface около 40 МБ.
Это за ряд или за весь комплект?
@Charlieface весь набор.
Разве где-то не должно быть await, если вы используете ToListAsync? Сколько всего строк в таблице и проиндексирован ли столбец ReceiverRuc?
@Charlieface Да, я пробовал. но тот же результат.
IncomingEmailId, объявите как первичный ключ.
На основании одного утверждения LINQ мы ничего не можем сказать об улучшении производительности. Посмотрите на план запроса, индексы, статистику и т. д. Возможно, при сериализации данных происходит ленивая загрузка.
Есть ли у вас индекс ReceiverRuc в таблице IncomingEmails? Если нет, попробуйте создать его и посмотрите, изменится ли это что-нибудь.
Вам нужны все данные для каждого электронного письма? Если на этом этапе вам не нужен Body для каждого электронного письма, вы, вероятно, сможете сэкономить много накладных расходов на передачу данных, исключив его из запроса. Если позже вам понадобится отобразить содержимое сообщения, вы можете повторно запросить базу данных только для этого сообщения.
Как говорит Герт, нам нужен план запроса, определения таблиц и определения индексов.





На ум приходят три вещи. Сначала убедитесь, что этот столбец ReceiveRuc проиндексирован в базе данных. Запрос данных к неиндексированному столбцу будет медленнее, особенно для таблиц с большим количеством данных.
Во-вторых, этот запрос, похоже, собирает больше информации, чем следовало бы. Предупреждающие флажки, которые я вижу, — это текст электронного письма и вложение. При извлечении тысяч строк для перебора рассмотрите возможность исключения тяжелых полей, которые не являются необходимыми в данный момент. Если вы действительно хотите в конечном итоге перебрать все 2000 результатов, вы можете получить эти тяжелые поля по идентификатору или даже объединить их и получить более мелкие группы по 10 или 100 за раз при обработке записей электронной почты.
В-третьих, это само вложение: это столбец в таблице электронной почты или строка в отдельной таблице вложений? Если это произойдет позже, вы захотите спроецировать это на упрощенный объект вложения, опять же с теми столбцами, которые вам нужны:
.Select(ie => new IncomingEmail
{
// Select only necessary properties
// ...
Attachment = new Attachment { ... }
// ...
}).ToListAsync();
Сам запрос требует await, если вы используете ToListAsync().
Следующее, что вы можете сделать, чтобы получить представление о том, что происходит, — это запустить профилировщик базы данных для захвата выполняемых операторов SQL. Виновниками, на которые следует обратить внимание, являются такие вещи, как отложенная загрузка вызовов. Например, если вы запустите этот метод и захватите строку SQL, которая загружает данные из электронного письма, но затем увидите около 2000 или около того дополнительных операторов SQL, извлекающих данные, относящиеся к некоторой таблице вокруг вложений (при условии, что вложение было строкой в другой таблице ), то вы можете столкнуться с ленивой загрузкой ссылок из включенного объекта вложения. Сама эта проблема будет решена путем проецирования вложения в новый контейнер. (Третий пункт выше). Тем не менее, при чтении данных профилировщик может помочь выявить проблемы с производительностью, связанные с отложенной загрузкой. Вы также можете проверить фактическое выполнение оператора SQL, чтобы получить план выполнения, который может дать советы по производительности.
Если навигационная опора Attachment содержит вложение большого содержимого, например byte[], это корень причины https://github.com/dotnet/SqlClient/issues/593. Попробуйте использовать методы синхронизации ToList вместо асинхронных методов ToListAsync, это должно решить проблему.
Сколько фактических данных в байтах?