Почему принудительное использование материализации с помощью ToList()
делает мои запросы на порядок быстрее, если что-либо, оно должно делать абсолютно противоположное?
1) Вызов First()
немедленно
// "Context" is an Entity Framework DB-first model
var query = from x in Context.Users
where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
select x;
var User = query.First();
// ** The above takes 30+ seconds to run **
2) Вызов First()
после вызова ToList()
:
var query = from x in Context.Users
where x.Username.ToLower().Equals(User.Identity.Name.ToLower())
select x;
var User = query.ToList().First(); // Added ToList() before First()
// ** Now it takes < 1 second to run! **
Обновление и разрешение
После получения сгенерированного SQL единственная разница, как и ожидалось, добавляет TOP (1)
в первый запрос. Как говорит Andyz Smith в своем ответе ниже, основной причиной является то, что оптимизатор SQL Server в этом конкретном случае выбирает худший план выполнения при добавлении TOP (1)
. Таким образом, проблема не имеет ничего общего с LINQ (что было правильно, добавив TOP (1)
) и все, что связано с особенностями SQL Server.