【问题标题】:Improve search performance in SQL Server through Entity Framework通过实体框架提高 SQL Server 中的搜索性能
【发布时间】:2014-03-02 10:29:09
【问题描述】:

我正在使用 SQL Server 2012 Express、Entity Framework 6 和 ASP.NET MVC 5。

在 SQL Server 中,我有一个包含 40 万条记录的 pricelist 表。价目表结构如下:

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

我还有一个price 表:

|Id|Price|CurrencyId|

还有一个currency 表:

|Id|Name|Alias|Value|

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

我需要从pricelist 获取20 条记录,其中NameDescription 包含 搜索查询并将其作为XML 返回。而且我需要不到一秒钟的时间来获取它们,因为这是全局搜索服务的条件之一(它的请求超时为 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 秒。如何提高性能?

【问题讨论】:

    标签: c# sql sql-server asp.net-mvc entity-framework


    【解决方案1】:

    不要使用包含。这完全不是实体框架问题,而是 SQL。

    pricelistRow.Name.Contains(搜索)

    翻译成 WHERE [Name] LIKE '%searchterm%'

    看到前面的 % 了吗?这意味着完整的数据扫描和索引没有帮助。

    替代方案:

    • StartsWith (LIKE 'searchterm%'),所以索引有效

    • 使用存储过程(EF 中没有其他方式),然后使用全文索引语法(EF 无法处理)。

    但除此之外 - 那是行不通的。像这样的条件意味着 - 在你的情况下 - 全表扫描。期间。

    【讨论】:

    • StartsWith 为我节省了大约 0.5 秒,并将结果减少到一条记录(这对我的数据样本不正确)。我可以只通过ExecuteSqlCommand 执行普通 SQL 命令,而不是使用存储过程(我从未使用过它们)进行全文索引查询吗?
    • @coshmos:“我从未使用过它们”不是不使用存储过程的好理由 :)
    • @DavidKhaykin,好的,我会试试看 :)
    • @TomTom,我会在尝试存储过程时标记您的答案。到周六。非常感谢。
    • 请注意,startswith 仅适用于索引 - 否则它仍然是扫描 - 并且完整的 ltext 需要表扫描。
    猜你喜欢
    • 2011-08-20
    • 1970-01-01
    • 2017-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多