[英]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.