SQL-запрос занимает слишком много времени в структуре сущностей с использованием ToList()

Я использую 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 09.05.2024 12:58

@Charlieface около 40 МБ.

Shashank Singh 09.05.2024 13:19

Это за ряд или за весь комплект?

Charlieface 09.05.2024 13:24

@Charlieface весь набор.

Shashank Singh 09.05.2024 13:34

Разве где-то не должно быть await, если вы используете ToListAsync? Сколько всего строк в таблице и проиндексирован ли столбец ReceiverRuc?

Charlieface 09.05.2024 13:39

@Charlieface Да, я пробовал. но тот же результат.

Shashank Singh 09.05.2024 13:42

IncomingEmailId, объявите как первичный ключ.

Shashank Singh 09.05.2024 13:44

На основании одного утверждения LINQ мы ничего не можем сказать об улучшении производительности. Посмотрите на план запроса, индексы, статистику и т. д. Возможно, при сериализации данных происходит ленивая загрузка.

Gert Arnold 09.05.2024 15:57

Есть ли у вас индекс ReceiverRuc в таблице IncomingEmails? Если нет, попробуйте создать его и посмотрите, изменится ли это что-нибудь.

Emilio Lucas Ceroleni 09.05.2024 16:08

Вам нужны все данные для каждого электронного письма? Если на этом этапе вам не нужен Body для каждого электронного письма, вы, вероятно, сможете сэкономить много накладных расходов на передачу данных, исключив его из запроса. Если позже вам понадобится отобразить содержимое сообщения, вы можете повторно запросить базу данных только для этого сообщения.

T N 09.05.2024 21:18

Как говорит Герт, нам нужен план запроса, определения таблиц и определения индексов.

Dale K 09.05.2024 23:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

На ум приходят три вещи. Сначала убедитесь, что этот столбец 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, это должно решить проблему.

Другие вопросы по теме