MaxLength及其如何影响查询

时间:2013-10-15 14:12:49

标签: sql sql-server performance entity-framework nvarchar

我正在使用Entity Framework 4.3.1,首先是代码,我正在查看正在生成的查询的SQL事件探查器。以下是一个例子:

如您所见 - 它将参数指定为nvarchar(max)但在我的配置中我指定了MaxLength值。因此,我希望参数将作为nvarchar(n)传递。由于它没有这样做,我们发现查询运行缓慢,这个简单的更改会加快它们的速度。

有谁知道我们如何说服实体框架生成正确的nvarchar长度?

这是我的实体和配置代码:

实体

public class StorageTransportOrderItem 
{
    public string StorageTransportOrderItemNumber { get; set; }
    public string StorageNumber { get; set; }
    [...]
}

配置

ToTable("StorageTransportOrderItem");

Property(p => p.StorageTransportOrderNumber)
    .HasMaxLength(10);
Property(d => d.StorageTransportOrderItemNumber)
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None)
    .HasMaxLength(4);

HasKey(d => new
{
    d.StorageTransportOrderItemNumber,
    d.StorageNumber,
    d.StorageTransportOrderNumber
 });

示例查询

FROM [dbo].[StorageTransportOrder] AS [Extent1]
WHERE ([Extent1].[StorageNumber] = @p__linq__0) AND ([Extent1]
[StorageTransportOrderNumber] = @p__linq__1)
)  AS [Limit1]',N'@p__linq__0 nvarchar(max) ,@p__linq__1 nvarchar(max)  
',@p__linq__0=N'200',@p__linq__1=N'0001374850'

注意nvarchar(max),这就是它变慢的原因。

1 个答案:

答案 0 :(得分:3)

Tl:dr; 我不认为HasMaxLength(),或者事实上你在使用Entity Framework时可以控制的任何东西都可以改变这一点,所以你可能应该看看在查询。

我的想法

我对你的查询获得nvarchar(max)的原因感到有点困惑 - 我希望nvarchar(4000)因为这是我在测试系统上得到的。这个问题提出了这个问题:Why does code first/EF use 'nvarchar(4000)' for strings in the raw SQL command?(非常有趣的阅读,那一个)。也许与ADO .Net版本有关,我不确定。

Anyhoo,我说我会建议你不能影响这个价值(至少,我相信你可以说服它nvarchar(4000)而不是nvarchar(max)当然但不是别的什么)。

认为在生成这些查询时,Entity Framework正在使用ADO .NET中的自动参数化功能(请参阅:How Data Access Code Affects Database Performance)。从本质上讲,我说我怀疑他们只是将字符串值添加到ADO .NET DbParameter并完成它。

这是一个真正的耻辱,因为你已经指定了MaxLength它确实知道该字段有多长,但我也可以想象用列来计算Lambda表达式中的参数有多复杂它涉及到,所以我并不完全惊讶。

那你能做什么?

鉴于你无法改变这一点,虽然它确实会影响性能,但正如你的建议,我建议你专注于减少运行这类查询的数量。通常,通过调整查询结构和计数而不是像这样的小事来做最好的性能改进(仅仅是我的经验,不要把它当作福音)。

例如,如果您在循环中执行类似SingleOrDefault(i => i.id ==x)的操作,则可能需要将其转换为循环外的单个Where(i => xs.Contains(i.id))。那种事。我不能真正详细说明,但我相信你将能够使用其他方法来获得足够的表现。

祝你好运!