Reputation: 7092
I have this method that returns true or false based on whether a website has any pages that have any external links.
The method does work. However, it is incredibly slow. Like it takes about 5 seconds to process a 100 websites with a combined total of 5000 pages.
protected bool WebsitesWithExternalLinks(int id)
{
var website = FetchModel(id);
if (website == null) return false;
//return true;
var externalLinks = website.WebPages
.Any(wp => wp.Links != null &&
wp.Links.ExternalLinks.Any());
return externalLinks;
}
I've pinpointed the slowness is occuring somewhere in the linq query, but I'm not quite sure why it's happening. I have other linq queries that operate on WebSite and WebSage objects that are quite fast.
I'm not sure why this one is so slow.
Is there any way to speed up linq queries or replace them with something else?
Upvotes: 0
Views: 112
Reputation: 109080
By the statement...
var website = FetchModel(id);
...you fetch one website
from the database. Then you access website.WebPages
. This loads all WebPages
of that website
in a separate query (lazy loading). Then for each of these pages, ExternalLinks
are queries in yet more separate queries until the first page is found having at least one external link. So if there are many pages with zero links, this make take a considerable amount of time.
The remedy is to do it in one query. Directly using a context it would look like this:
var externalLinks =
context.Websites
.Any(w => w.Id == id
&& w.WebPages
.Any(wp => wp.Links.ExternalLinks.Any()));
This will execute one query that only return a boolean.
I can't tell from here how this fits into your architecture. Depends on how deeply you buried the context and how much freedom you allowed yourself to shape the queries you execute with it.
Upvotes: 3