2014-02-05 56 views
3

我使用SQL Server 2012 Express中,實體框架6和ASP.NET MVC 5通過實體框架提高SQL Server的搜索性能

在SQL Server我有一個pricelist表40萬條記錄。價格表的結構如下:

|Id|Manufacturer|Name|Description|StockQuantity|PriceId| 

此外,我已經有了一個price表:

|Id|Price|CurrencyId| 

並有currency表:

|Id|Name|Alias|Value| 

NameDescription列索引由SQL Server全文索引。

我需要從pricelist,其中NameDescription包含搜索查詢並返回它作爲XML得到20條記錄。我需要讓它們少於一秒,因爲它是全局搜索服務的一個條件(它的請求超時是1秒,我無法更改它)。這是一個結果XML的結構:

<items> 
    <item mfr="PC" Name="Laptop" Description="2.4GHz, etc." StockQuantity="500" P1="100" P2="200" P3="300" Cur="USD"/> 
</items> 

P1P2P3是不同訂單的數量價格。

我使用這個代碼來獲取記錄:

using (var db = new DatabaseContainer()) { 
    db.Configuration.AutoDetectChangesEnabled = false; 
    db.Configuration.ValidateOnSaveEnabled = false; 
    db.Configuration.LazyLoadingEnabled = false; 

    var result = 
     (from pricelistRow in db.EFPricelist 
     where pricelistRow.Name.Contains(search) || pricelistRow.Description.Contains(search) 
      select new Result { 
      Manufacturer = pricelistRow.Manufacturer, 
      Name = pricelistRow.Name, 
      Description = pricelistRow.Description, 
      StockQuantity = pricelistRow.StockQuantity, 
      P1 = pricelistRow.EFPricelistRowPrice.Any() ? SqlFunctions.StringConvert(pricelistRow.EFPricelistRowPrice.Min(x => x.Price)) : "", 
      P2 = pricelistRow.EFPricelistRowPrice.Count() == 3 ? SqlFunctions.StringConvert(pricelistRow.EFPricelistRowPrice.OrderBy(x => x.Price).Skip(1).FirstOrDefault().Price) : "", 
       P3 = pricelistRow.EFPricelistRowPrice.Count() > 1 ? SqlFunctions.StringConvert(pricelistRow.EFPricelistRowPrice.Max(x => x.Price)) : "", 
       Cur = pricelistRow.EFPricelistRowPrice.Any() ? pricelistRow.EFPricelistRowPrice.FirstOrDefault().EFCurrency.Alias : "" 
        }).Take(20).ToList(); 
    return new XmlResult(new Result { 
     Items = result 
    }); 
} 

前後歷時約2秒。我怎樣才能提高性能?

回答

4

請勿使用包含。這完全不是一個實體框架問題 - 但是SQL。

pricelistRow.Name.Contains(搜索)

轉化爲WHERE [名稱] LIKE '%搜索關鍵詞%'

看到前面的%?這意味着完整的數據掃描和索引不起作用。

替代方案:

  • StartsWith(LIKE '搜索關鍵詞%'),所以索引工作

  • 使用存儲過程(在EF沒有其他方法),然後全文索引語法(這EF無法處理)。

但是,否則 - 這是行不通的。如果這樣的條件意味着 - 就你的情況而言 - 全表掃描。期。

+0

'StartsWith'爲我節省了大約0.5秒,並將結果減少到一條記錄(這對我的數據樣本不正確)。我可以通過ExecuteSqlCommand而不是使用存儲過程(我從來沒有使用它們)執行純SQL命令來進行全文索引查詢嗎? – colotiline

+1

@coshmos:「我從來沒有使用它們」不是一個很好的理由不使用存儲過程:) –

+0

@DavidKhaykin,好的,我會嘗試他們:) – colotiline