Entity Framework Vs Stored Procedures - Performance Measure
Asked Answered
I

4

81

I'm trying to establish how much slower Entity Framework is over Stored Procedures. I hope to convince my boss to let us use Entity Framework for ease of development.

Problem is I ran a performance test and it looks like EF is about 7 times slower than Stored Procs. I find this extremely hard to believe, and I'm wondering if I'm missing something. Is this a conclusive Test? Is there anything I can do to increase the performance of the EF Test?

        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);

Result:

SP - 10000 Queries took 2278

Entity - 10000 Queries took 16277

Isa answered 16/3, 2012 at 14:35 Comment(1)
I would like to add that unboxing should suffice instead of explicitly doing converts. so do: (string)dr["MobileAlias"] instead of .ToString()Corettacorette
W
112

There are some things you can do to optimize your query. Here on MSDN you can find a nice overview.

But to be honest, a stored procedure with manual mapping will always be faster in performance. But ask yourself, how important is performance? In most projects, development time is way more important then performance. What was harder to develop? The raw query with parsing or the Entity Framework query?

ORMs are not designed because they perform so much better than a hand written approach. We use them because development is so much easier!

If you write your application with the Entity Framework and hide all your queries behind a repository pattern you can develop real quick and then, when performance becomes an issue, measure your application to detect the bottleneck. Then maybe some of your queries need optimization and can be moved to stored procedures and manual mapping.

Whitneywhitson answered 16/3, 2012 at 14:48 Comment(18)
your users will disagree with you that developer time is more important than theirs... especially when they're sitting watching that spinning hourglass! That said, why not write the sql in sprocs and call them using EF - best of both worlds?Juxtaposition
If you have a spinning hourglass you have a real scenario that you can optimize. To get to that scenario developer productivity is in my opinion more important then premature optizationWhitneywhitson
I was wondering since years about a reallife example of the Repository Pattern. Now I have. Thank you :)Mandrel
@WouterdeKort What if you have multiple databases and you don't control all of them. That is, what if you can't write stored procedures for Oracle, SQL Server, MySQL, & Postgres for that one query.Melitta
@Melitta If you have multiple databases that can all be accessed by using a single ORM you're really lucky. In reality, Entity Framework has providers for different databases and not all databases are supported. In such scenarios, I think you will always run into writing optimizations per database. But I think the same principles apply: don't do premature optimization but make sure you know where the bottlenecks are and optimze them.Whitneywhitson
It would be better if we use Stored Procedure to read data and ORM like Entity Framework to do CRUD operations ?Sick
@gbjbaanb: For the average user, you're right. But the average user isn't the one deciding the budget and/or deadline for the development. This is also very dependent on the business. E.g. I developed a social security platform where any changes to the business logic (= laws that were passed) needed to be pushed ASAP. The fastest way to intelligently adapt bsiness logic with minimal code impact was Entity Framework. Regardless of a marginally longer loading time. And that's the point: different scenarios weigh development time vs performance time diffferently.Adelia
@Adelia in my experience, the time taken to push a product change is 10% code, 90% testing, packaging, deployment, and administration. That's successfully push product changes, of course!Juxtaposition
@Juxtaposition How does that change the need to minimize the time needed to update the codebase? One would assume that testing and packaging is ceteris paribus, no different between the options of using and avoiding EF. If anything, the stored proc approach has more chance of stalling deployment because it's a second task (uodating the database), whereas EF work by only reinstalling the apllication libraries .Adelia
@Adelia it doesn't, it means the time needed is irrelevant when it comes down to it. Ask a DBA, they'll show you how to do it properly. You should have a DBA doing the production DB anyway. Imagine if you changed the DB schema in your code change, eg adding a new column, or new index. Code First has plenty of ways to fail doing that.Juxtaposition
@Juxtaposition No it doesn't. That's the whole point of code first. The DB structure is autogenerated from the classes. You don't need to involve a dba for every change you make.Adelia
I have used both, Code First is a great idea, until it gets complicated and then it fall apart and you're having to use SQL (or fluent API to force SQL in) anyway. You don't need a DBA to update a DB using SQL, but if you had one your DB would run a lot better than if your DBA is a C# coder. If you did it the SQL way you'd realise it is a lot better - but I guess all you have is a hammer.Juxtaposition
@Juxtaposition I'm sorry but I have to disagree. Having only a DBA touch production is production is no longer feasible in a modern world where applications are updated multiple times a day. Entity Framework migrations, SQL Server Data Tools or the tooling from Red Gate are all there to optimize these processes. This does involve a DBA but also optimizes the whole flow.Whitneywhitson
@gbjbaanb: I'd say worst of both worlds. Because you are losing the dev time advantage, since you're going to manually write the code for the SP & do the mapping yourself. And chances are that you'll be losing the LINQ advantage since any projections, filtering etc will be made inside the SPs in SQL. Therefore, what benefit do U get from EF then?Colic
@Colic well, I use Dapper these days for my sprocs, considering how well received it's been, and the reason it was created, I'd say using EF is not what I'd recommend any more. Write your DB as an API, don't try to mix it in with your app code.Juxtaposition
@gbjbaanb: I agree, there are some cases that Dapper is easier. as will all the things, it depends. However, I'll disagree that users will complain on the performance vs dev time argument because the performance benefit is usually negligible and with EF you can always take over and write the SQL yourself when you detect such a performance bottleneck. In my world users do complain when a simple change takes too much time to do. As for the "DB code as an API..don't try to mix it with your code", why does it have to be written in SQL in order to be an API and separated from other code?Colic
I haven't found that EF has saved me development time. I have tried it multiple times. Either my work must be extremely complicated compared to most developers (I doubt that) or I am just a heck of a lot dumber (I also doubt that). Or... perhaps I'm more pragmatic and I understand that some code is just boring/mundane to write and that feels like a waste of time to many developers; and many developers are more concerned about what "feels" like a waste of their time than what actually is wasted time. I find that stored procs ultimately make for much faster development.Orestes
Seems you have always worked for terrible projects and execution. Performance is always on priority than development time. What is the meaning of delivering something if it can't be used with 100 users 😂Accumulative
J
16

In agreement with @Wouter de Kort ... Moreover, when you need to move to procedures, you can use EF in conjunction with procedures to assist migration from one to the other.

Moving to procedures will be faster in a typical application if you unify functionality into well designed procedures. i.e. Get as much work done in one sproc call as possible. For example, in a shopping cart MVC app when a user clicks the check-out button, you might use the ORM to something like:

  1. look up a user's authentication (is the login still valid?)
  2. look up permissions (can they purchase said items?, are there special requirements?)
  3. look up stock quantities to make sure they were not depleted in process
  4. write to DB to reserve (remove from available inventory) items before payment
  5. look up payment info
  6. logging ... ?

Or it may be completely different steps, but in any case, the point is, the MVC app will use an ORM to make multiple calls to the DB to get to the next step.

If all this logic is encapsulated in one well written sproc then there is just one call to the sproc and you're done. With the MVC-ORM route the data must be copied from the DB to the driver and delivered to ORM (usually over the net to a different host) and then read by the MVC app to make a simple decision then repeated until all steps are complete. In the case of using a sproc that encapsulates that check-out step, there is a lot less data copying and moving to be done, less network IO, less context switching etc.

Think of the MVC-ORM solution this way. Person "A" is knowledgeable of facts only and person "B" has all the savvy to make decisions with given facts which he does not poses. Person "B" emails "A" for facts. Based on the answer from "A", "B" might request a few more facts before making a decision. That's a lot of back and forth messaging.

If you have one person that has all facts and the knowledge to make decisions, you just need to ask one question and their brain will process everything internally to come up with an answer. No deliberation with another person is involved. Naturally it's going to be faster.

That's not to say it's necessarily better. Separating facts from decision means that these components are separately replaceable / testable however, if you are married to your MVC and your DB then that's a "non-issue".

On the other hand many MVC fans hate writing SQL so they consider putting any decision logic into SQL as a natural disaster. For such people it's imperative to have any logic written in the same language that the MVC uses because it speeds up development for them. In some cases this is also a "non-issue" since in the case of some RDMBS you can write sprocs in the same language as the one used by the MVC (examples: .Net - SQL Server sprocs can be written in C# and use .Net ; Postgresql functions (no sprocs) can be written in Perl, Python, PHP et. al) The advantage in this case is that you can have fast sprocs that encapsulate multiple steps in one call and you can use a programming language that you are already quick in coding in.

Juliannajulianne answered 1/4, 2013 at 18:19 Comment(2)
I used C# for sprocs once.. terrible performance. SQL was significantly faster. I think it had something to do with the managed->unmanaged transitions, but either way : use the right tool for the job, not the "C# hammer"Juxtaposition
If performance is imperative and you don't mind writing C++ then you could write extended stored procedures in C++ which should (if done right) beat anything else and it will be exceptionally leaner than #Juliannajulianne
T
7

I can think of 2 very good reasons why I would choose stored procedures over ORMs

  1. The advantages of encapsulation are well documented. You wouldn't ever create a class and then expect users of that class to interact with the inner workings of the class. What if something changed; what if you changed a variable type? How would you know where all the code that accessed that variable was? Solution, use an interface. Your database is no different, it's an object, so give it an interface. For SQL Server databases, that means stored procedures.

  2. Having worked as a DBA for over 20 years, I've lost count of the number of times developers have describe a problem with code that they wrote as "A database problem", and suggested "Talk to the DBA" as a solution. Now, I don't mind this. When I'm fixing your mistakes, and you're not fixing mine... well let's just say it's something I will definitely raise during performance review. But the least you can do is code in a fashion which allows me to fix your mistakes in the shortest time possible. That means, put your code in stored procedures. When stored procedures cause performance issues, that's bread and butter for any decent DBA. But when ORMs cause performance issues, that's a nightmare for anyone. At least give your DBA a fighting chance when he's trying to help you.

And if you can't code in stored procedures, or it really takes you that much longer to do so, then you might want to think about a change of career.

Tashia answered 22/7, 2021 at 23:2 Comment(0)
S
6

It is important to note that

Starting with the .NET Framework 4.5, LINQ queries are cached automatically. However, you can still use compiled LINQ queries to reduce this cost in later executions and compiled queries can be more efficient than LINQ queries that are automatically cached.

From MSDN Compiled Queries (LINQ to Entities)

Subtenant answered 5/4, 2019 at 10:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.