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

Я пытаюсь установить, насколько медленнее 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

Ответы [ 3 ]

80 голосов
/ 16 марта 2012

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

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

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

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

10 голосов
/ 01 апреля 2013

По согласованию с @Wouter de Kort ... Более того, когда вам нужно перейти к процедурам, вы можете использовать EF вместе с процедурами, чтобы облегчить переход с одной на другую.

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

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

Или это могут быть совершенно разные шаги, но в любом случае, суть в том, что приложение 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, которые инкапсулируют несколько шагов за один вызов, и вы можете использовать язык программирования, который вы уже быстро в кодировании.

2 голосов
/ 05 апреля 2019

Важно отметить, что

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

СMSDN скомпилированные запросы (LINQ to Entities)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...