linq to sql startwith performance索引列

我首先使用实体​​代码。 索引列:

  • SourceCatalogId
  • CategoryPath

表中有40 000行,

我的问题是查询需要40s !!

var result = DBContext.Set() .Include(x => x.SalesHistories, x => x.SourceCatalog) .Where(p => p.SourceCatalogId == 2) .where(p => p.Disabled == false) .where(x => x.CategoryPath.StartsWith("MyPath")) .orderby(x => x.ShortDesignation) .Skip(1) .Take(10) .toList(); 

SQL通过sql profiler:

 exec sp_executesql N'SELECT TOP (10) [Project1].[SourceProductId] AS [SourceProductId], [Project1].[SourceSKU] AS [SourceSKU], [Project1].[SourceCatalogId] AS [SourceCatalogId], [Project1].[ManufacturerReference] AS [ManufacturerReference], [Project1].[Disabled] AS [Disabled], [Project1].[EAN] AS [EAN], [Project1].[ShortDesignation] AS [ShortDesignation], [Project1].[FullDesignation] AS [FullDesignation], [Project1].[Description] AS [Description], [Project1].[Url] AS [Url], [Project1].[CategoryPath] AS [CategoryPath], [Project1].[Condition] AS [Condition], [Project1].[BuyingPriceHT] AS [BuyingPriceHT], [Project1].[ShippingPriceHT] AS [ShippingPriceHT], [Project1].[PublicSellingPriceHT] AS [PublicSellingPriceHT], [Project1].[PictureUrl1] AS [PictureUrl1], [Project1].[PictureUrl2] AS [PictureUrl2], [Project1].[PictureUrl3] AS [PictureUrl3], [Project1].[PictureUrl4] AS [PictureUrl4], [Project1].[Quantity] AS [Quantity], [Project1].[AddDate] AS [AddDate], [Project1].[UpdateDate] AS [UpdateDate], [Project1].[Followers] AS [Followers] FROM ( SELECT [Project1].[SourceProductId] AS [SourceProductId], [Project1].[SourceSKU] AS [SourceSKU], [Project1].[SourceCatalogId] AS [SourceCatalogId], [Project1].[ManufacturerReference] AS [ManufacturerReference], [Project1].[Disabled] AS [Disabled], [Project1].[EAN] AS [EAN], [Project1].[ShortDesignation] AS [ShortDesignation], [Project1].[FullDesignation] AS [FullDesignation], [Project1].[Description] AS [Description], [Project1].[Url] AS [Url], [Project1].[CategoryPath] AS [CategoryPath], [Project1].[Condition] AS [Condition], [Project1].[BuyingPriceHT] AS [BuyingPriceHT], [Project1].[ShippingPriceHT] AS [ShippingPriceHT], [Project1].[PublicSellingPriceHT] AS [PublicSellingPriceHT], [Project1].[PictureUrl1] AS [PictureUrl1], [Project1].[PictureUrl2] AS [PictureUrl2], [Project1].[PictureUrl3] AS [PictureUrl3], [Project1].[PictureUrl4] AS [PictureUrl4], [Project1].[Quantity] AS [Quantity], [Project1].[AddDate] AS [AddDate], [Project1].[UpdateDate] AS [UpdateDate], [Project1].[Followers] AS [Followers], row_number() OVER (ORDER BY [Project1].[ShortDesignation] ASC) AS [row_number] FROM ( SELECT [Extent1].[SourceProductId] AS [SourceProductId], [Extent1].[SourceSKU] AS [SourceSKU], [Extent1].[SourceCatalogId] AS [SourceCatalogId], [Extent1].[ManufacturerReference] AS [ManufacturerReference], [Extent1].[Disabled] AS [Disabled], [Extent1].[EAN] AS [EAN], [Extent1].[ShortDesignation] AS [ShortDesignation], [Extent1].[FullDesignation] AS [FullDesignation], [Extent1].[Description] AS [Description], [Extent1].[Url] AS [Url], [Extent1].[CategoryPath] AS [CategoryPath], [Extent1].[Condition] AS [Condition], [Extent1].[BuyingPriceHT] AS [BuyingPriceHT], [Extent1].[ShippingPriceHT] AS [ShippingPriceHT], [Extent1].[PublicSellingPriceHT] AS [PublicSellingPriceHT], [Extent1].[PictureUrl1] AS [PictureUrl1], [Extent1].[PictureUrl2] AS [PictureUrl2], [Extent1].[PictureUrl3] AS [PictureUrl3], [Extent1].[PictureUrl4] AS [PictureUrl4], [Extent1].[Quantity] AS [Quantity], [Extent1].[AddDate] AS [AddDate], [Extent1].[UpdateDate] AS [UpdateDate], [Extent1].[Followers] AS [Followers] FROM [dbo].[SourceProducts] AS [Extent1] WHERE ([Extent1].[SourceCatalogId] = @p__linq__0) AND (0 = [Extent1].[Disabled]) AND ([Extent1].[CategoryPath] LIKE @p__linq__1 ESCAPE N''~'') ) AS [Project1] ) AS [Project1] WHERE [Project1].[row_number] > 0 ORDER BY [Project1].[ShortDesignation] ASC',N'@p__linq__0 bigint,@p__linq__1 nvarchar(4000)',@p__linq__0=2,@p__linq__1=N'MyPath%' 

在where子句之前的最后一个,如果我删除“ escape N”〜” ”:

 WHERE ([Extent1].[SourceCatalogId] = @p__linq__0) AND (0 = [Extent1].[Disabled]) AND ([Extent1].[CategoryPath] LIKE @p__linq__1 ESCAPE N''~'') 

查询需要4s。

这是正常的吗? 索引使用? 我如何用startWith解决它?

编辑

categoryPath的索引属性:

 [Index("IX_SourceProduct_SourceCatalogId_Disabled_CategoryPath", 3), StringLength(400)] public string CategoryPath { get; set; } 

EDIT2

好吧,我很接近,我认为问题是存储过程。

 string search = "julien"; var list = db.Users.Where(x => x.Name.StartsWith(search)); string query = list.ToString(); 

=> SELECT [Extent1]。[UserId] AS [UserId],[Extent1]。[Name] AS [Name] FROM [dbo]。[Users] AS [Extent1] WHERE [Extent1]。[Name] LIKE @ p__linq__0 ESCAPE N ‘〜’

 var list2 = db.Users.Where(x => x.Name.StartsWith("julien")); string query2 = list2.ToString(); 

=> SELECT [Extent1]。[UserId] AS [UserId],[Extent1]。[Name] AS [Name] FROM [dbo]。[Users] AS [Extent1] WHERE [Extent1]。[Name] LIKE N’julien %”

因此,如果我在查询中使用变量来获取存储过程,如果我使用const我得到选择。

在存储过程中(由实体生成)使得出现@ p__linq__0所以添加ESCAPE N’〜 以避免变量中的wildCaractere。

所以现在问题更简单了。 如何避免变量查询? 这是可能的 ? 谢谢

所以你需要做的是获取变量的值并将其用作生成的Expression中的常量。 这实际上是非常可能的。 我们需要的是一个表达式,它接受你想要的参数作为真实选择器的参数,作为第二个参数,它是常量值的占位符,然后是你想要成为常量的值。 然后我们可以用常量的值替换参数的所有实例,只留下一个将真实参数映射到结果的函数:

 public static Expression> EmbedConstant ( this Expression> expression, TConstant constant) { var body = expression.Body.Replace( expression.Parameters[1], Expression.Constant(constant)); return Expression.Lambda>( body, expression.Parameters[0]); } 

这依赖于以下方法将一个表达式的所有实例替换为另一个:

 public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx) { return new ReplaceVisitor(searchEx, replaceEx).Visit(expression); } internal class ReplaceVisitor : ExpressionVisitor { private readonly Expression from, to; public ReplaceVisitor(Expression from, Expression to) { this.from = from; this.to = to; } public override Expression Visit(Expression node) { return node == from ? to : base.Visit(node); } } 

这允许您映射:

 string search = "julien"; var list = db.Users.Where(x => x.Name.StartsWith(search)); string query = list.ToString(); 

进入这个:

 string search = "julien"; Expression> predicate = (item, searchTerm) => item.Name.StartsWith(searchTerm); var list = db.Users.Where(predicate.EmbedConstant(search)); string query = list.ToString();