簡體   English   中英

改善自動完成LINQ查詢的性能

[英]Improve the performance of an AutoComplete LINQ Query

我的AutoComplete正在進行大量搜索,想知道是否有人可以提出任何建議來提高性能。

怎么了:

1)在應用程序啟動時,我將所有數據庫條目保存在內存中。

2)用戶在搜索框中鍵入以啟動自動完成:

$("#MatterCode").width(110).kendoAutoComplete({
        minLength: 3,
        delay: 10,
        dataTextField: "MatterCode",
        template: '<div class="autoCompleteResultsCode"> ${ data.ClientCode } - ${ data.MatterCode } - ${ data.ClientName } - ${ data.MatterName }</div>',
        dataSource: {
            serverFiltering: true,
            transport: {
                read: "/api/matter/AutoCompleteByCode",
                parameterMap: function() {
                    var matterCode = $("#MatterCode").val();
                    return { searchText: matterCode };
                }
            }
        }, //More Stuff here

3)進入我的控制器類:

public JsonResult AutoCompleteByCode(string searchText)
{
    if (string.IsNullOrEmpty(searchText))
    {
        Response.StatusCode = 500;
        return Json(new
        {
            Error = "search string can't be empty"
        });
    }

    var results = _publishedData.GetMattersForAutoCompleteByCode(searchText).Select(
            matter => new
            {
                MatterCode = matter.Code,
                MatterName = matter.Name,
                ClientCode = matter.Client.Code,
                ClientName = matter.Client.Name
            });
    return Json(results);
}

4)進入DAL的對象(以“ _”開頭的對象是內存對象)

public virtual IEnumerable<Matter> GetMattersForAutoCompleteByCode(string input)
{
    InvalidateCache();
    IEnumerable<Matter> results;
    //Searching Matter Object on all 4 given parameters by input.

    if (_lastMatters != null && input.StartsWith(_lastSearch) && _lastMatters.Any())
    {
        results = _lastMatters.Where(m => m.IsInputLike(input)).OrderBy(m => m.Code);
        _lastMatters = results;
    }
    else
    {
        results = _matters.Where(m => m.IsInputLike(input)).OrderBy(m => m.Code);
        _lastMatters = results;
    }

    _lastSearch = input;

    return results.Take(10).ToList();
}

5)isInputLike是一個內部布爾方法

internal bool IsInputLike(string input)
{
    //Check to see if the input statement exists in any of the 4 fields
    bool check = (Code.ToLower().Contains(input.Trim().ToLower()) 
            || Name.ToLower().Contains(input.Trim().ToLower()) 
            || ClientCode.ToLower().Contains(input.Trim().ToLower()) 
            || ClientName.ToLower().Contains(input.Trim().ToLower()));

    return check;
}

現在,我必須使用的結果集可能超過100,000。 現在,任何新查詢的第一個自動完成功能都必須搜索40萬條記錄,我想不出一種不犧牲功能就可以提高性能的方法。

有任何想法嗎? SQL存儲的proc調用是否比LINQ更快?

我不是一個asp / http家伙,但是當我看到此信息時:

internal bool IsInputLike(string input)
{
    //Check to see if the input statement exists in any of the 4 fields
    bool check = (Code.ToLower().Contains(input.Trim().ToLower()) 
        || Name.ToLower().Contains(input.Trim().ToLower()) 
        || ClientCode.ToLower().Contains(input.Trim().ToLower()) 
        || ClientName.ToLower().Contains(input.Trim().ToLower()));

    return check;
}

我認為您正在創建很多新的字符串。 這需要一些時間。 試試看,看看這是否可以改善您的表現

var inp = input.Trim();
bool chk = (Code.IndexOf(inp, StringComparison.CurrentCultureIgnoreCase) > -1)
                || (Name.IndexOf(inp, StringComparison.CurrentCultureIgnoreCase) > -1)
                || (ClientCode.IndexOf(inp, StringComparison.CurrentCultureIgnoreCase) > -1)
                || (ClientName.IndexOf(inp, StringComparison.CurrentCultureIgnoreCase) > -1);

第一行(創建inp)並不重要,因為編譯器應該優化重復使用,但是我認為它讀起來更好。

IndexOf方法不會創建新的字符串,並且使用StringComparison參數可以避免創建所有ToLower字符串。

我認為這里的主要問題是首先將400k對象放置在內存中。 SQL並沒有那么慢,最好首先從一組有限的數據開始。

一個明顯的優化是:

internal bool IsInputLike(string input)
{
    string input = input.Trim().ToLower();
    //Check to see if the input statement exists in any of the 4 fields
    bool check = (Code.ToLower().Contains(input) 
            || Name.ToLower().Contains(input) 
            || ClientCode.ToLower().Contains(input) 
            || ClientName.ToLower().Contains(input));

    return check;
}

但就我個人而言,我會將數據保留在SQL Server中(如果您使用的是它)。 一些索引和適當的查詢可以使此過程更快。

當我看到這段代碼時,我開始懷疑:

public virtual IEnumerable<Matter> GetMattersForAutoCompleteByCode(string input)
{
    InvalidateCache();
    IEnumerable<Matter> results;
    //Searching Matter Object on all 4 given parameters by input.

    if (_lastMatters != null && input.StartsWith(_lastSearch) && _lastMatters.Any())
    {
        results = _lastMatters.Where(m => m.IsInputLike(input)).OrderBy(m => m.Code);
        _lastMatters = results;
    }
    else
    {
        results = _matters.Where(m => m.IsInputLike(input)).OrderBy(m => m.Code);
        _lastMatters = results;
    }

    _lastSearch = input;

    return results.Take(10).ToList();
}

為什么需要訂購? 為什么下拉式自動填充功能需要過濾4個項目? 如果你只拿10點,就不能不點菜嗎? 查看刪除orderby是否會給您帶來更好的結果,尤其是在else語句中,您將獲得很多結果。

我個人將全力以赴使用LINQ to SQL,並讓SQL Server進行搜索。 優化此表上的索引編制,它將更快。

好吧,我建議您創建一個包含所有名稱的視圖,例如將所有名稱(如(代碼,名稱,Clientcode,ClientName)放入一個連接成FullName的單列中,並替換IsInputLike(..)如下:

internal bool IsInputLike(string input)
{
    //Check to see if the input statement exists in any of the 4 fields
    return FullName.Contains(input);

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM