简体   繁体   中英

Improving search performance on websites database

Is there any way to improve this query, I am quite satisfied by the results returned but performance is really bad, does union in this case causes round-trip? Would something like this be possible by using Stored Procedure to gain on preformance? Is it possible to do something like self join on results and would it increase performance?

        List<string> words = Util.Search.SplitByWhiteSpace(q);

        using (WebsitesDataContext context = new WebsitesDataContext())
        {
            IQueryable<WebsitesRanked> query = Enumerable.Empty<WebsitesRanked>().AsQueryable();
            query = query.Union(context.Websites.Where(x => x.Title.Contains(q)).Select(x => new WebsitesRanked { Webiste = x, Rank = 100 }));
            query = query.Union(context.Websites.Where(x => x.Description.Contains(q)).Select(x => new WebsitesRanked { Webiste = x, Rank = 100 }));
            query = query.Union(context.Websites.Where(x => x.Keywords.Contains(q)).Select(x => new WebsitesRanked { Webiste = x, Rank = 100 }));
            query = query.Union(context.Websites.Where(x => x.Url.Contains(q)).Select(x => new WebsitesRanked { Webiste = x, Rank = 100 }));

            foreach (var word in words)
            {
                string keyword = word;
                query = query.Union(context.Websites.Where(x => x.Title.Contains(word)).Select(x => new WebsitesRanked { Webiste = x, Rank = 20 }));
                query = query.Union(context.Websites.Where(x => x.Description.Contains(word)).Select(x => new WebsitesRanked { Webiste = x, Rank = 20 }));
                query = query.Union(context.Websites.Where(x => x.Keywords.Contains(word)).Select(x => new WebsitesRanked { Webiste = x, Rank = 20 }));
                query = query.Union(context.Websites.Where(x => x.Url.Contains(word)).Select(x => new WebsitesRanked { Webiste = x, Rank = 20 }));
            }

           var results = query.GroupBy(x => x.Webiste).Select(x => new WebsitesRanked { Webiste = x.First().Webiste, Rank =  x.Sum(s => s.Rank) }).OrderByDescending(x => x.Rank).Select(x => x.Webiste);
        }

you can create dictionary table: one table partition by letter (table partition for word starting with 'a', another 'b'...) this table will have those columns:

column 1:Word (each word in your table will be setted here using a nightly schedule task or Background schedule task)
column 2:Website 
column 3:Rank (each time a word is found, increment this rank)

with only one table to query and using partition to be performant, you will have good performance because the work will be done for you on a schedule task

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