I’m trying to optimize a query which is taking around 6 seconds to execute.
string[] filters = ...;
var data =
(from n in ctx.People
.Where(np => np.IsActive)
let isFilterMatch = filters.All(f => n.FirstName.ToLower().Contains(f) ||
n.Prefix.ToLower().Contains(f) ||
n.MiddleName.ToLower().Contains(f) ||
n.LastName.ToLower().Contains(f) ||
n.Information.Email.ToLower().Contains(f) ||
(n.Address!= null &&
(SqlFunctions.StringConvert((double)n.Address.Number).
Contains(f) ||
n.Address.Street.ToLower().Contains(f) ||
n.Address.ZipCode.ToLower().Contains(f) ||
n.Address.City.ToLower().Contains(f))))
where isFilterMatch
orderby n.LastName
select n
).Take(numberOfItems).ToList();
This is a query for a search dialog. The user can type in any text and it will then search for a person that matches the input. We split the user input into a string array and then do a Contains on the Person fields. The query cannot be precompiled because of the filter array.
How can I optimize this function? I heard about things like FullTextSearch on Sql Server or stored procedures. Could that help?
We are using Sql Server 2008, Entity Framework 4.0 (Model First) and C#.
I would not use a SQL query / Linq query for this search query. Normal queries for text searching can be slow and they only return exact results; they don’t correct spelling/grammar errors etc.
You might consider using the ‘Full Text Search’ functionality of SQL Server; but the resulting performance might be still poor. Please refer to http://www.sql-server-performance.com/2010/full-text-search-2008/.
I would suggest to use a search indexer like Apache Lucene (which is available as a dll in Lucene.NET). Another option is that you write your own Windows service that indexes all the records.