У меня есть тест, в котором много записей с течением времени. Я использую postgresql для хранения этих тестов и записей и хочу иметь возможность искать тесты, записи которых попадают в определенный временной диапазон.
У теста много записей, и у каждой записи есть значение collectionTime, которое хранится как DateTime. Когда я ищу все тесты, я использую следующий запрос с использованием EFCore и Linq:
На этом этапе я начинаю выполнять различную фильтрацию и сортировку. Это изменяет результирующий запрос в зависимости от того, какие фильтры применяет пользователь. Если пользователь просто извлекает все записи, в этот момент они разбиваются на страницы и возвращаются без фильтрации, то с запросом нет проблем. Однако, когда я добавляю свою логику для проверки того, был ли предоставлен определенный период времени, мой запрос постоянно истекает по времени.
У меня есть почти идентичное условие для проверки того, находится ли время сбора FirstReported после providedEndDate, так как фильтрация обеих сторон таким образом логически приводит к желаемым мной тестам.
После разбиения результатов на страницы я отправляю их в список: return await tests.ToListAsync(token);
Я также хочу подсчитать количество записей для целей разбиения на страницы, и CountAsync также останавливается при фильтрации тестов в диапазоне дат.
Есть ли какие-либо предложения или непосредственные опасения по поводу запроса и логики относительно того, почему этот запрос так плохо работает/истекает по времени? Я думаю, что это довольно распространенное явление, но я не могу найти никаких конкретных сообщений, которые бы касались оптимизации поиска таким образом. Спасибо
var tests = Table.Include(t => t.RecordData).AsSplitQuery().AsNoTracking()
.Select(r => new Test
{
Id = r.Id,
...additional test info here...
FirstReported = r.RecordData.OrderBy(rd => rd.CollectionDate).FirstOrDefault().CollectionDate,
LastReported = r.RecordData.OrderByDescending(rd => rd.CollectionDate).FirstOrDefault().CollectionDate,
NumberOfRecords = r.RecordData.Count,
});
if (providedStartDate is not null)
{
var startDateUTC = providedStartDate.ToUniversalTime().Date;
tests = tests.Where(x => x.NumberOfRecords > 0 && x.LastReported >= startDateUTC);
}