Истекло время ожидания запросов EF Linq, но те же запросы менее 1 секунды на SSMS
сначала я попробовал ARITHABORT OFF
на SSMS это все еще менее 1 секунды.
я использую EntityFrameWork: 6.1.3 и Azure Sql S1 tier (я попробую с уровнем 3 и дам вам знать, если что-то изменится.)
Я использую EF Profiler для получения сгенерированного sql из linq. Я запросил все linqs, которые я поделился, все они меньше 1 секунды на SSMS.
у меня есть 3 миллиона recods на таблице AuditLog. Один клиент с ID 3 имеет 170k записывает другого клиента с ID 35 имеет 125 записей. Я сведу код к минимуму.
Модель AuditLog:
public class AuditLog
{
public long? CustomerId { get; set; }
[ForeignKey("CustomerId")]
public virtual CustomerSummary Customer { get; set; }
[Required]
[Index]
public DateTime CreatedDate { get; set; }
}
первый запрос:
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
если я попытаюсь с клиентом, у которого есть 170k строк, он дает исключение тайм-аута. Если я попробую с клиентом, у которого 125 записей, это нормально.
Второй Запрос: то же самое с первым, я просто включаю клиентов.
if (customer != null)
{
var customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
результат противоположен первому запросу. если я попробую с клиентом, который имеет 170k строк, все в порядке. Если я попытаюсь с клиентом,у которого есть 125 записей, он дает исключение тайм-аута.
третий запрос: это то же самое с первым запросом, но я соответствую long?
о том, где для customerId.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).ToList();
}
результат противоположен первому запросу. если я попробую с клиентом, у которого есть 170k строк, все в порядке. Если я попытаюсь с клиентом,у которого есть 125 записей, он дает исключение тайм-аута.
четвертый вопрос: это то же самое со вторым запросом, но я матч long?
о том, где для customerId.
if (customer != null)
{
long? customerId = customer.Id;
var result= Dbset.Where(x => x.CustomerId == customerId).OrderByDescending(x => x.CreatedDate).Skip(0).Take(25).Include(x => x.Customer).ToList();
}
результат противоположен второму запросу. если я попробую с клиентом, у которого есть 170k строк, он дает исключение тайм-аута. Если я попробую с клиентом, у которого 125 записей, это нормально.
я совсем запуталась. Почему внутреннее соединение или изменение параметра соответствуют long?
меняются результаты ? И почему это все запросы выполняются под 1 сек на SSMS и дают ошибку на EF linq ?
ошибка:
{System.Данные.В sqlclient.SqlException (0x80131904): истекло время ожидания. Время ожидания истекло до завершения операции или сервер не отвечает. ---> Система.ComponentModel.Win32Exception (0x80004005): тайм-аут операции ожидания на Система.Данные.В sqlclient.Объект sqlconnection.OnError (исключение SqlException, Boolean breakConnection, действие ' 1 wrapCloseInAction)
обновление (19/04/2016):
после Иван Стоев предложение на комментарии.
вы пробовали (только ради теста), используя hardcoded 3 и 35 вместо
customerId
переменной?
Я не получил никакой ошибки, и запросы самые быстрые, как на SSMS.
обновление (20/04/2016): реальная проблема Нюхают Параметр. Когда я включил или изменил параметр на nullable, на самом деле я создал другие запросы и другой запрос планировавший. Я создал некоторые планы с клиентом, у которого есть 125 записей, а другие-с клиентом, у которого есть 170k записей этих 4 запросов. Вот почему я получил разные результаты.
1 ответов
то, что вы испытываете, является результатом так называемого Проблема Нюхания Параметров. До сих пор я не знаю простого общего решения, поэтому обычно предлагаю обходной путь, устраняя некоторые параметры SQL-запроса, вручную связывая постоянные значения внутри выражений, как в EntityFramework LINQ query count завершается ошибкой, но запрос возвращает результат. Как оптимизировать запрос LINQ?.
для вашего сценария я бы предложил следующее пользовательское расширение метод:
public static class QueryableExtensions
{
public static IQueryable<T> WhereEquals<T, TValue>(this IQueryable<T> source, Expression<Func<T, TValue>> selector, TValue value)
{
var predicate = Expression.Lambda<Func<T, bool>>(
Expression.Equal(selector.Body, Expression.Constant(value)),
selector.Parameters);
return source.Where(predicate);
}
}
а затем обновите свой фрагмент следующим образом
if (customer != null)
{
var result= Dbset.WhereEquals(x => x.CustomerId.Value, customer.Id)
.OrderByDescending(x => x.CreatedDate)
.Skip(0).Take(25)
.Include(x => x.Customer)
.ToList();
}