Entity Framework работает слишком медленно. Какие у меня варианты? [закрытый]



я следовал мантре "не оптимизируйте преждевременно" и закодировал свою службу WCF с помощью Entity Framework.



тем не менее, я профилировал производительность и Entity Framework слишком медленно. (Мое приложение обрабатывает 2 сообщения примерно за 1,2 секунды, где (устаревшее) приложение, которое я переписываю, делает 5-6 сообщений за одно и то же время. (Устаревшее приложение вызывает хранимые процедуры для доступа к БД.)



мое профилирование указывает на Entity Framework, занимая большую часть времени за сообщение.



Итак, каковы мои варианты?




  • есть ли там лучшие Ормы?

    (То, что просто поддерживает нормальное чтение и запись объектов и делает это быстро..)


  • есть ли способ сделать Entity Framework быстрее?

    (Примечание: когда я говорю быстрее, я имею в виду в долгосрочной перспективе, а не первый звонок. (Первый вызов медленный (15 секунд для сообщения), но это не проблема. Мне просто это нужно будьте быстры для остальных сообщений.)


  • какой-то таинственный 3-й вариант, который поможет мне получить больше скорости из моего сервиса.



Примечание: большинство моих взаимодействий с БД-это создание и обновление. Я очень мало выбираю и удаляю.

1333   13  

13 ответов:

вы должны начать с профилирования команд SQL, фактически выпущенных Entity Framework. В зависимости от вашей конфигурации (POCO, Self-Tracking entities) есть много места для оптимизации. Вы можете отлаживать команды SQL (которые не должны отличаться между режимом отладки и выпуска) с помощью ObjectSet<T>.ToTraceString() метод. Если вы столкнулись с запросом, который требует дальнейшей оптимизации, вы можете использовать некоторые прогнозы, чтобы дать EF дополнительную информацию о том, что вы пытаетесь выполнять.

пример:

Product product = db.Products.SingleOrDefault(p => p.Id == 10);
// executes SELECT * FROM Products WHERE Id = 10

ProductDto dto = new ProductDto();
foreach (Category category in product.Categories)
// executes SELECT * FROM Categories WHERE ProductId = 10
{
    dto.Categories.Add(new CategoryDto { Name = category.Name });
}

заменить на:

var query = from p in db.Products
            where p.Id == 10
            select new
            {
                p.Name,
                Categories = from c in p.Categories select c.Name
            };
ProductDto dto = new ProductDto();
foreach (var categoryName in query.Single().Categories)
// Executes SELECT p.Id, c.Name FROM Products as p, Categories as c WHERE p.Id = 10 AND p.Id = c.ProductId
{
    dto.Categories.Add(new CategoryDto { Name = categoryName });
}

Я просто набрал это из моей головы, так что это не совсем так, как это будет выполняться, но EF на самом деле делает некоторые хорошие оптимизации, если вы расскажете ему все, что знаете о запросе (в этом случае нам понадобятся имена категорий). Но это не похоже на нетерпеливую загрузку (db.Товары.Включить ("категории")), поскольку прогнозы могут еще больше сократить объем загружаемых данных.

дело в том, что такие продукты, как Entity Framework, всегда будут медленными и неэффективными, потому что они выполняют намного больше кода.

Я также считаю глупым, что люди предлагают оптимизировать запросы LINQ, посмотреть на сгенерированный SQL, использовать отладчики, предварительно скомпилировать, предпринять много дополнительных шагов и т. д. т. е. тратить много времени. Никто не говорит - упростите! Каждый хочет, чтобы комликать вещи дальше, принимая еще больше шагов (тратить время).

A здравый смысл подход будет не использовать EF или LINQ вообще. Используйте простой SQL. В этом нет ничего плохого. Просто потому, что есть стадный менталитет среди программистов, и они чувствуют желание использовать каждый новый продукт там, не означает, что это хорошо или это будет работать. Большинство программистов думают, что если они включают каждый новый фрагмент кода, выпущенный большой компанией, это делает их более умным программистом; совсем не так. Умное программирование в основном о том, как сделать больше с меньшим головные боли, неуверенность, и в наименьшее количество времени. Помните-Время! Это самый важный элемент, поэтому постарайтесь найти способы не тратить его на решение проблем в плохом / раздутом коде, написанном просто в соответствии с некоторыми странными так называемыми "шаблонами"

расслабьтесь, наслаждайтесь жизнью, сделайте перерыв в кодировании и прекратите использовать дополнительные функции, код, продукты, "шаблоны". Жизнь коротка, и жизнь вашего кода еще короче, и это, конечно, не ракетостроение. Удаление таких слоев, как LINQ, EF и другие, и ваш код будет работать эффективно, будет масштабироваться, и да, он по-прежнему будет легко поддерживать. Слишком много абстракции-это плохая "модель".

и это решение вашей проблемы.

одно из предложений заключается в использовании LINQ to Entity Framework только для операторов CRUD с одной записью.

для более сложных запросов, поисков, отчетов и т. д. напишите хранимую процедуру и добавьте ее в модель Entity Framework, как описано на MSDN.

Это подход, который я принял с несколькими моими сайтами, и это, кажется, хороший компромисс между производительностью и производительностью. Entity Framework не всегда будет генерировать наиболее эффективный SQL для задача под рукой. И вместо того, чтобы тратить время, чтобы выяснить, почему, написание хранимой процедуры для более сложных запросов на самом деле экономит время для меня. После того, как вы знакомы с процессом, это не слишком много хлопот, чтобы добавить сохраненные процессы к вашей модели EF. И, конечно же, преимущество добавления его в вашу модель заключается в том, что вы получаете все, что сильно типизировано, что происходит от использования ORM.

Если вы чисто извлечение данных, это большая помощь для производительности, когда вы говорите EF, чтобы не отслеживать объекты, которые он извлекает. Сделайте это с помощью MergeOption.NoTracking. EF просто сгенерирует запрос, выполнит его и десериализует результаты в объекты, но не будет пытаться отслеживать изменения сущностей или что-либо в этом роде. Если запрос прост (не тратит много времени на ожидание возврата базы данных), я обнаружил, что установка его в NoTracking может удвоить запрос спектакль.

см. эту статью MSDN о перечислении MergeOption:

разрешение идентификации, управление состоянием и отслеживание изменений

Это, кажется, хорошая статья о производительности EF:

производительность и Entity Framework

вы говорите, что вы профилировали приложение. Вы тоже профилировали ОРМ? Существует профилировщик EF от Ayende, который выделит, где вы можете оптимизировать свой код EF. Вы можете найти его здесь:

http://efprof.com/

помните, что вы можете использовать традиционный подход SQL вместе с вашим ORM, если вам нужно, чтобы получить производительность.

Если есть более быстрый / лучший ORM? В зависимости от вашей модели объекта / данных вы можете рассмотреть возможность использования один из микро-Ормов, таких как щеголеватый,огромные или PetaPoco.

сайт Dapper публикует некоторые сравнительные тесты, которые дадут вам представление о том, как они сравниваются с другими ОРМ. Но стоит отметить, что микро-ORMs не поддерживают богатый набор функций полных ORMs, таких как EF и NH.

вы можете взглянуть на RavenDB. Это нереляционная база данных (от Ayende снова), которая позволяет вам магазин покос напрямую без сопоставление нужны. RavenDB оптимизирован для чтения и делает жизнь разработчиков намного проще, устраняя необходимость манипулировать схемой и сопоставлять ваши объекты с этой схемой. Однако имейте в виду, что это значительно другой подход к использованию подхода ORM, и они изложены в сайт продукта.

по моему опыту, проблема не с EF, а с самим подходом ORM.

вообще все Ормы страдают от N+1 проблема не оптимизированные запросы и т. д. Мое лучшее предположение состояло бы в том, чтобы отслеживать запросы, которые вызывают снижение производительности, и пытаться настроить инструмент ORM или переписать эти части с помощью SPROC.

Я нашел ответ на @Slauma здесь очень полезно для ускорения вещи. Я использовал один и тот же шаблон для вставки и обновления - и производительность взлетела.

имеет смысл оптимизировать только после профилирования. Если вы обнаружите, что доступ к БД медленный, вы можете преобразовать его в использование хранимых процедур и сохранить EF. Если вы обнаружите, что сам EF медленный, вам, возможно, придется переключиться на другой ORM или вообще не использовать ORM.

Это простой вариант без рамок, без ORM, который загружается со скоростью 10 000 в секунду с 30 полями или около того. Работает на старом ноутбуке, так что, вероятно, быстрее, чем в реальной среде.

https://sourceforge.net/projects/dopersistence/?source=directory

Я столкнулся с этой проблемой, а также. Я ненавижу сваливать на EF, потому что он работает так хорошо, но это просто медленно. В большинстве случаев я просто хочу найти запись или обновить/вставить. Даже простые операции, как это медленно. Я вытащил 1100 записей из таблицы в список, и эта операция заняла 6 секунд с EF. Для меня это слишком долго, даже сохранять слишком долго.

Я закончил тем, что сделал свой собственный ОРМ. Я вытащил те же 1100 записей из базы данных, и мой ORM занял 2 секунды, много быстрее, чем эф. Все с моей ОРМ почти мгновенно. Единственное ограничение прямо сейчас заключается в том, что он работает только с MS SQL Server, но его можно изменить для работы с другими, такими как Oracle. Я использую MS SQL Server для всего прямо сейчас.

Если вы хотите попробовать мой ОРМ вот ссылка и сайт:

https://github.com/jdemeuse1204/OR-M-Data-Entities

или если вы хотите использовать самородок:

PM> Install-Package Или-M_DataEntities

документация там тоже

платформа Entity Framework не должна сама вызывать серьезные узкие места. Скорее всего, есть и другие причины. Вы можете попробовать переключить EF на Linq2SQL, оба имеют функции сравнения, и код должен быть легко конвертирован, но во многих случаях Linq2SQL быстрее, чем EF.

У нас есть аналогичное приложение (Wcf -> EF -> database), которое легко выполняет 120 запросов в секунду, поэтому я более чем уверен, что EF здесь не ваша проблема, что, как говорится, я видел значительные улучшения производительности с скомпилированными запросами.

Я использовал EF, LINQ to SQL и dapper. Щеголь-самый быстрый. Пример: мне нужно было 1000 основных записей с 4 вспомогательными записями каждая. Я использовал LINQ to sql, это заняло около 6 секунд. Затем я переключился на dapper, извлек 2 набора записей из одной хранимой процедуры и для каждой записи добавил дополнительные записи. Общее время 1 секунда.

также хранимая процедура использовала функции табличных значений с перекрестным применением, я нашел скалярные функции значений очень медленными.

мой совет был бы используйте EF или LINQ to SQL и для определенных ситуаций переключитесь на dapper.

Comments

    Ничего не найдено.