Я вижу действительно странную производительность, связанную с очень простым запросом с использованием Entity Framework Code-First с .NET framework версии 4. Запрос LINQ2Entities выглядит следующим образом:
context.MyTables.Where(m => m.SomeStringProp == stringVar);
На это уходит более 3000 миллисекунд. Сгенерированный SQL выглядит очень просто:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
...
FROM [MyTable] as [Extent1]
WHERE [Extent1].[SomeStringProp] = '1234567890'
Этот запрос выполняется почти мгновенно при запуске через Management Studio. Когда я меняю код C # для использования функции SqlQuery, она выполняется за 5-10 миллисекунд:
context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);
Таким образом, точно такой же SQL, в результирующих объектах отслеживаются изменения в обоих случаях, но разница в производительности между ними очень велика. Что дает?
performance
entity-framework
ef-code-first
Брайан Салливан
источник
источник
Performance Considerations for Entity Framework 5
Ответы:
Нашел. Оказывается, проблема в типах данных SQL.
SomeStringProp
Столбец в базе данных была VARCHAR, но EF предполагает , что строковые типы .NET являются nvarchars. Результирующий процесс перевода во время запроса к БД для сравнения занимает много времени. Я думаю, что EF Prof немного сбивал меня с пути, более точное представление выполняемого запроса было бы следующим:SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp], ... FROM [MyTable] as [Extent1] WHERE [Extent1].[SomeStringProp] = N'1234567890'
Таким образом, полученное исправление состоит в том, чтобы аннотировать модель с первым кодом, указав правильный тип данных SQL:
public class MyTable { ... [Column(TypeName="varchar")] public string SomeStringProp { get; set; } ... }
источник
varchar
для всего, и это действительно была проблема. Интересно, могу ли я сделать EDMX для рассмотрения varchar для всего строкового столбца.Причина замедления моих запросов, сделанных в EF, заключалась в сравнении скаляров, не допускающих значения NULL, со скалярами, не допускающими значения NULL:
long? userId = 10; // nullable scalar db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value ^^^^^^^^^ ^^^^^^ Type: long Type: long?
Этот запрос занял 35 секунд. Но вот такой крошечный рефакторинг:
long? userId = 10; long userIdValue = userId.Value; // I've done that only for the presentation pursposes db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList() ^^^^^^^^^ ^^^^^^^^^^^ Type: long Type: long
дает невероятные результаты. Это заняло всего 50 мсек. Возможно, это ошибка в EF.
источник
Если вы используете свободное отображение, вы можете использовать
IsUnicode(false)
как часть конфигурации, чтобы получить тот же эффект -http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9
http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx
источник
У меня была такая же проблема (запрос выполняется быстро из диспетчера SQL), но при выполнении из EF истекает время ожидания.
Оказывается, объект (который был создан из представления) имел неправильные ключи объекта. Таким образом, у объекта были повторяющиеся строки с одинаковыми ключами, и я предполагаю, что он должен был выполнить группировку на заднем плане.
источник
Я также столкнулся с этим со сложным запросом ef. Одно исправление для меня, которое сократило 6-секундный запрос ef до сгенерированного субсекундного запроса sql, заключалось в отключении ленивой загрузки.
Чтобы найти этот параметр (ef 6), перейдите в файл .edmx и посмотрите Свойства -> Генерация кода -> Ленивая загрузка включена. Установите значение false.
Значительное улучшение производительности для меня.
источник
У меня тоже была эта проблема. Оказывается, в моем случае виноват анализ параметров SQL-сервера .
Первым признаком того, что моя проблема на самом деле возникла из-за обнюхивания параметров, было то, что выполнение запроса с «set arithabort off» или «set arithabort on» приводило к резко различающимся временам выполнения в Management Studio. Это связано с тем, что в ADO.NET по умолчанию используется «отключение арифметики», а в Management Studio по умолчанию - «включение арифметики». Кэш планов запроса хранит разные планы в зависимости от этого параметра.
Я отключил кеширование плана запроса для запроса, решение, которое вы можете найти здесь .
источник