Подтвердить что ты не робот

Entity Framework Vs Сохраненные процедуры - оценка эффективности

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

Проблема заключается в том, что я провел тест производительности, и похоже, что EF примерно в 7 раз медленнее, чем хранимые процедуры. Мне очень трудно поверить, и мне интересно, не хватает ли я чего-то. Это убедительный тест? Есть ли что-то, что я могу сделать, чтобы повысить производительность теста 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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

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

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

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

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

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