Я последовал мантре «Не оптимизируйте преждевременно» и написал свою службу WCF с помощью Entity Framework.
Однако я проанализировал производительность, и Entity Framework работает слишком медленно. (Мое приложение обрабатывает 2 сообщения примерно за 1,2 секунды, в то время как (устаревшее) приложение, которое я переписываю, выполняет 5-6 сообщений одновременно (устаревшее приложение вызывает sprocs для доступа к БД).
Мои профилирование указывает на то, что Entity Framework занимает большую часть времени на сообщение.
Итак, какие у меня варианты?
Есть ли лучшие ORM?
(Что-то, что поддерживает нормальное чтение и запись объектов и делает это быстро ..)Есть ли способ сделать Entity Framework быстрее?
( Примечание : когда я говорю «быстрее», я имею в виду долгий срок, а не первый вызов. (Первый вызов медленный (15 секунд для сообщения), но это не проблема. Мне просто нужно, чтобы он был быстрым для остальных сообщений.)Какой-то таинственный третий вариант, который поможет мне получить больше скорости от моей службы.
ПРИМЕЧАНИЕ. Большинство моих взаимодействий с БД - это создание и обновление. Я очень мало выделяю и удаляю.
источник
Ответы:
Вы должны начать с профилирования команд SQL, фактически выданных Entity Framework. В зависимости от вашей конфигурации (POCO, Self-Tracking entity) есть много возможностей для оптимизации. Вы можете отлаживать команды 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.Products.Include ("Categories")), потому что проекции могут еще больше уменьшить объем данных для загрузки.
источник
Дело в том, что такие продукты, как Entity Framework, ВСЕГДА будут медленными и неэффективными, потому что они выполняют намного больше кода.
Я также считаю глупым то, что люди предлагают оптимизировать запросы LINQ, смотреть на сгенерированный SQL, использовать отладчики, выполнять предварительную компиляцию, предпринимать много дополнительных шагов и т. Д., Т.е. тратить много времени. Никто не говорит - упрощайте! Каждый хочет еще больше усложнить ситуацию, делая еще больше шагов (тратя время).
Здравый смысл заключается в том, чтобы вообще не использовать 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
источник
Вы говорите, что профилировали приложение. Вы тоже профилировали ORM? Существует профилировщик EF от Ayende, который укажет, где вы можете оптимизировать код EF. Вы можете найти это здесь:
http://efprof.com/
Помните, что вы можете использовать традиционный SQL-подход вместе с ORM, если вам нужно повысить производительность.
Есть ли более быстрый / лучший ORM? В зависимости от вашей модели объекта / данных вы можете рассмотреть возможность использования одного из микро-ORM, например Dapper , Massive или PetaPoco. .
Сайт Dapper публикует несколько сравнительных тестов, которые дадут вам представление о том, как они сравниваются с другими ORM. Но стоит отметить, что микро-ORM не поддерживают богатый набор функций полных ORM, таких как EF и NH.
Вы можете взглянуть на RavenDB . Это нереляционная база данных (снова от Ayende), которая позволяет хранить POCO напрямую без необходимости сопоставления . RavenDB оптимизирован для чтения и значительно упрощает жизнь разработчикам, устраняя необходимость манипулировать схемой и сопоставлять ваши объекты с этой схемой. Однако имейте в виду, что это существенно другой подход к использованию подхода ORM, и они описаны на сайте продукта .
источник
Я нашел ответ @Slauma здесь очень полезным для ускорения работы. Я использовал один и тот же шаблон как для вставок, так и для обновлений - и производительность резко возросла.
источник
По моему опыту, проблема не в EF, а в самом подходе ORM.
В общем, все ORM страдают от проблемы N + 1, не оптимизированных запросов и т. Д. Лучше всего было бы отследить запросы, которые вызывают снижение производительности, и попытаться настроить инструмент ORM или переписать эти части с помощью SPROC.
источник
Это простой вариант без фреймворка, без ORM, который загружается со скоростью 10 000 в секунду с 30 полями или около того. Работает на старом ноутбуке, вероятно, быстрее, чем в реальной среде.
https://sourceforge.net/projects/dopersistence/?source=directory
источник
Я тоже столкнулся с этой проблемой. Ненавижу выгружать EF, потому что он работает так хорошо, но просто медленно. В большинстве случаев я просто хочу найти запись или обновить / вставить. Даже такие простые операции выполняются медленно. Я извлек 1100 записей из таблицы в список, и эта операция с EF заняла 6 секунд. Для меня это слишком долго, даже сохранение занимает слишком много времени.
В итоге я сделал свой собственный ORM. Я извлек те же 1100 записей из базы данных, и мой ORM занял 2 секунды, что намного быстрее, чем EF. Все с моим ORM происходит почти мгновенно. Единственное ограничение на данный момент заключается в том, что он работает только с MS SQL Server, но его можно изменить для работы с другими, такими как Oracle. Я использую MS SQL Server для всего прямо сейчас.
Если вы хотите попробовать мой ORM, вот ссылка и веб-сайт:
https://github.com/jdemeuse1204/OR-M-Data-Entities
Или, если вы хотите использовать самородок:
PM> Install-Package OR-M_DataEntities
Там же есть документация
источник
Оптимизация имеет смысл только после профилирования. Если вы обнаружите, что доступ к БД медленный, вы можете перейти на использование хранимых процедур и сохранить EF. Если вы обнаружите, что медленным является сам EF, возможно, вам придется переключиться на другой ORM или вообще не использовать ORM.
источник
У нас есть похожее приложение (Wcf -> EF -> database), которое легко выполняет 120 запросов в секунду, поэтому я более чем уверен, что EF - не ваша проблема, при этом я заметил значительные улучшения производительности с помощью скомпилированных запросов.
источник
Я использовал EF, LINQ to SQL и dapper. Dapper самый быстрый. Пример: мне нужно 1000 основных записей по 4 подзаписи в каждой. Я использовал LINQ to sql, это заняло около 6 секунд. Затем я переключился на dapper, получил 2 набора записей из одной хранимой процедуры и для каждой записи добавил вспомогательные записи. Общее время 1 секунда.
Также хранимая процедура использовала функции табличных значений с перекрестным применением, я обнаружил, что функции скалярных значений очень медленные.
Я бы посоветовал использовать EF или LINQ to SQL и в определенных ситуациях переключиться на dapper.
источник
Entity Framework сама по себе не должна вызывать серьезных узких мест. Скорее всего, есть и другие причины. Вы можете попробовать переключить EF на Linq2SQL, оба имеют функции сравнения, и код должен быть легко преобразован, но во многих случаях Linq2SQL быстрее, чем EF.
источник