Entity Framework против хранимых процедур - показатель эффективности

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

Проблема в том, что я запустил тест производительности, и похоже, что EF примерно в 7 раз медленнее, чем Stored Procs. Мне очень трудно в это поверить, и мне интересно, что я что-то упустил. Это убедительный тест? Что я могу сделать, чтобы повысить производительность теста EF?

        var queries = 10000;

        //  Stored Proc Test
        Stopwatch spStopwatch = new Stopwatch();
        spStopwatch.Start();
        for (int i = 0; i < queries; i++ )
        {
            using (var sqlConn = new SlxDbConnection().Connection)
            {
                var cmd = new SqlCommand("uspSearchPerformanceTest", sqlConn) { CommandType = CommandType.StoredProcedure };

                cmd.Parameters.AddWithValue("@searchText", "gstrader");
                sqlConn.Open();
                SqlDataReader dr = cmd.ExecuteReader();

                List<User> users = new List<User>();
                while (dr.Read())
                {
                    users.Add(new User
                    {
                        IsAnonymous = Convert.ToBoolean(dr["IsAnonymous"]),
                        LastActivityDate = Convert.ToDateTime(dr["LastActivityDate"]),
                        LoweredUserName = dr["LoweredUserName"].ToString(),
                        MobileAlias = dr["MobileAlias"].ToString(),
                        UserId = new Guid(dr["UserId"].ToString()),
                        UserName = (dr["UserName"]).ToString()
                    });
                }

                var username = users.First().UserName;
                sqlConn.Close();
            }
        }
        spStopwatch.Stop();
        Console.WriteLine("SP - {0} Queries took {1}", queries, spStopwatch.ElapsedMilliseconds );

        //  EF  Test
        Stopwatch entityStopWatch = new Stopwatch();

        var context = new SlxDbContext();
        var userSet = context.Set<User>();
        entityStopWatch.Start();
        for (int i = 0; i < queries; i++)
        {
            User user = userSet.Where(x => x.UserName == "gstrader").First();
        }

        entityStopWatch.Stop();
        Console.WriteLine("Entity - {0} Queries took {1}", queries, entityStopWatch.ElapsedMilliseconds);

Результат:

SP - 10000 запросов заняло 2278

Entity - 10000 запросов заняло 16277

 Alex07 февр. 2017 г., 17:36
Я хотел бы добавить, что распаковка должна быть достаточной, вместо явного преобразования. так же: (строка) dr ["MobileAlias"] вместо .ToString ()

Ответы на вопрос(2)

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

Переход к процедурам будет быстрее в типичном приложении, если выунифицировать функциональность в хорошо разработанные процедуры. т.е. получить как можно больше работы заодин вызов sproc по возможности. Например, в приложении MVC корзины покупок, когда пользователь нажимает кнопку извлечения, вымог бы используйте ORM для чего-то вроде:

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

Или это могут быть совершенно разные шаги, но в любом случае дело в том, что приложение MVC будет использовать ORM, чтобы сделать несколько обращений к БД, чтобы перейти к следующему шагу.

Если вся эта логика заключена в одном хорошо написанном sproc, то есть только один вызов sproc, и все готово. При маршруте MVC-ORM данные должны быть скопированы из БД в драйвер и доставлены в ORM (обычно через сеть на другой хост), а затем прочитаны приложением MVC, чтобы принять простое решение, затем повторяться до завершения всех шагов , В случае использования sproc, который инкапсулирует этот этап извлечения, будет гораздо меньше копирования и перемещения данных, меньше сетевого ввода-вывода, меньше переключения контекста и т. Д.

Подумайте о решении MVC-ORM таким образом. Человек «А» осведомлен только о фактах, а человек «Б» обладает достаточным умом принимать решения с учетом фактов, которые он не представляет. Человек "B" отправляет электронное письмо "A" для фактов Исходя из ответа «А», «Б» может потребовать еще несколько фактов, прежде чем принимать решение. Это много сообщений туда и обратно.

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

Это не значит, что это обязательнолучше, Отделение фактов от решения означает, что эти компоненты можно заменять / тестировать отдельно, однако, если вы состоите в браке с вашим MVC и вашей БД, то это «не проблема».

С другой стороны, многие поклонники MVC ненавидят писать SQL, поэтому считают естественной катастрофой любую логику принятия решений в SQL. Для таких людей обязательно иметь какую-либо логику, написанную натот же язык, который использует MVC потому что это ускоряет развитие для них. В некоторых случаях это также «не проблема», поскольку в случае некоторых RDMBS вы можете писать sprocs на том же языке, что и язык, используемый MVC (примеры: .Net - sprocs SQL Server могут быть написаны на C # и использовать .Net; Функции Postgresql (без sprocs) могут быть написаны на Perl, Python, PHP и др. Преимуществом в этом случае является то, что вы можете иметь быстрые sprocs, которые инкапсулируют несколько шагов за один вызов, и вы можете использовать язык программирования, который вы уже быстро в кодировании.

 gbjbaanb28 февр. 2014 г., 13:24
Я использовал C # для sprocs однажды .. ужасная производительность. SQL был значительно быстрее. Я думаю, что это как-то связано с управляемыми -> неуправляемыми переходами, но в любом случае: используйте правильный инструмент для работы, а не «молоток C #»
 MikeM05 мар. 2014 г., 23:38
Если производительность является императивом, и вы не против написания C ++, тогда вы можете написать расширенные хранимые процедуры на C ++, которые должны (если все сделано правильно) превзойти все остальное, и это будет исключительно меньше, чем
Решение Вопроса

которые вы можете сделать, чтобы оптимизировать свой запрос.Здесь на MSDN Вы можете найти хороший обзор.

Но, если честно, хранимая процедура с ручным отображением всегда будет быстрее в производительности. Но спросите себя, насколько важна производительность? В большинстве проектов время разработки гораздо важнее, чем производительность. Что было сложнее развивать? Необработанный запрос с разбором или запрос Entity Framework?

ORM не разработаны, потому что они работают намного лучше, чем рукописный подход. Мы используем их, потому что разработка намного проще!

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

 gbjbaanb28 февр. 2014 г., 10:46
Ваши пользователи не согласятся с вами, что время разработчика важнее, чем у них ... особенно когда они сидят и смотрят на вращающиеся песочные часы! Тем не менее, почему бы не написать sql в sprocs и вызвать их, используя EF - лучший из обоих миров?
 johnny05 янв. 2017 г., 21:19
@WouterdeKort Что делать, если у вас есть несколько баз данных, и вы не контролируете их все. То есть, если вы не можете написать хранимые процедуры для Oracle, SQL Server, MySQL и Postgres для этого одного запроса.
 Christian Gollhardt30 мар. 2016 г., 06:12
Я много лет интересовался реальным примером паттерна репозитория. Теперь у меня есть. Спасибо :)
 Wouter de Kort02 июл. 2018 г., 10:16
@gbjbaanb Извините, но я должен не согласиться. Производство только с использованием сенсорного управления DBA - это производство, которое больше невозможно в современном мире, где приложения обновляются несколько раз в день. Миграции Entity Framework, инструменты данных SQL Server или инструменты от Red Gate - все это для оптимизации этих процессов. Это включает в себя DBA, но также оптимизирует весь поток.
 Wouter de Kort28 февр. 2014 г., 15:55
Если у вас есть вращающиеся песочные часы, у вас есть реальный сценарий, который вы можете оптимизировать. Чтобы достичь такого сценария, продуктивность разработчика на мой взгляд важнее, чем преждевременная оптимизация.

Ваш ответ на вопрос