简体   繁体   中英

Linq to Entities : Count is very slow

I need to have parent and parent.child.count()....in the query.. when i do this it is taking 20 seconds....its not a huge database...Any ideas for optimization...

var plist = context.persons
  .Select(p => new
  {
    p.fullName,
    c.personID,
    p.Status,
    p.Birthdate,
    p.Accounts.Count
  }).ToList();

Here is a great article on using count() when you really meant to use any()

http://blogs.teamb.com/craigstuntz/2010/04/21/38598/

Do you need to use .count or could you use .any?

http://msdn.microsoft.com/en-us/library/bb534972.aspx

Since this is entity framework, open up the sql profiler and take a look at what sql queries are being sent to the database. It sounds like you may see that a single query is sent to fetch the group identifiers, and then another set of queries (one for each group) might be fetching the count. If that's happening, you'll have to post the linq query for someone to resolve the issue.

Based on the code you sent, it doesn't look like things should be taking that long. I have a few suggestions:

  1. Use LinqPad to do this query. It will let you see the SQL that gets generated. Then run that SQL code in SQL Server Management Studio, and tell it to include the actual execution plan. This will help you learn whether there's a particular point in the query that's taking a lot of time. For example, if you don't have an index on the Account table's PersonId reference, this query will take a lot longer.
  2. Look at how you're using this data. It's very rare that you really need to have all the people in your entire system in memory at the same time. In fact, I suspect that simply getting all this person data out of the database is probably taking a lot more time than the Count() is.
    • Are you displaying this data? If so, wouldn't it be better to "page" the results, only showing maybe ten entries at a time? You can use the .Take(int) method before calling .ToList() to get only as many entries as you need.
    • If you're processing and aggregating this data for the sake of site metrics, it's probably better to set up your query to return the end result before it gets evaluated.

If you can describe how this data is being used, or provide a screenshot of the SQL's execution, we can provide more feedback.

I had a somehow similar problem, I tried these and worked out better :

child.count(x=> x.paretnID == inputParentID) child.where(x=> x.parentID == inputParentID)

my original code which took around 15-20 seconds on each iteration was: return (isEdit) ? db.ChasisBuys.Single(x => x.ChasisBuyID == long.Parse(Request.QueryString["chbid"])).Chasises.Count(y => y.Bikes.Count > 0 && y.ColorID == buyItems[(int)index].ColorID && y.ChasisTypeID == buyItems[(int)index].ChasisTypeID).ToString() : "-";

new code which runs good is :

        **return (isEdit) ? db.Chasises.Where(x => x.ChasisBuyID == long.Parse(Request.QueryString["chbid"])).Count(y => y.Bikes.Count > 0 && y.ColorID == buyItems[(int)index].ColorID && y.ChasisTypeID == buyItems[(int)index].ChasisTypeID).ToString() : "-";**

Database has around 1000 records in chasises , about 5 in chasisBuys and about 20 in Bikes. my opinion is that Linq to SQL queries does not do preevaluations such in logical statements which for instance if you write "return a && b && c;" if statement a is false other statements are not evaluated and I was expecting such thing in linq to sql but it's not the case.

I solved a similar problem using the GroupBy method.

IEnumerable> accounts = Accounts.GroupBy(x => x.personID); accounts.Count() will return the number of accounts that belong to the person. accounts.Key will return the personID of the group.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM