我有一些使用“实体框架代码优先”创建的数据库;应用程序正常运行,总的来说,我对Code First的功能感到非常满意。根据需要,我首先是一名程序员,然后是DBA。我正在阅读有关DataAttributes的信息,以在C#中进一步描述我希望数据库做什么。我的问题是:如果将这些nvarchar(max)字符串放在表中(请参见下面的示例),我将受到什么惩罚?在C#中,它们的定义如下:

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int ID { get; set; }
    public string Name { get; set; }
    public string Message { get; set; }
    public string Source { get; set; }
    public DateTime Generated { get; set; }
    public DateTime Written { get; set; }


我希望根据名称,源,生成的和书面形式进行查询和/或排序。我希望“名称和源”的长度为0-50个字符,偶尔最多为150个字符。我希望此表的开头很小(<100k行),但随着时间的推移会显着增长(> 1m行)。显然,消息可能是大小,可能不会被查询。

我想知道的是,当我从未期望过将Name和Source列定义为nvarchar(max)时,是否会对性能产生影响?大于150个字符?

评论

看起来您需要应用[MaxLength]或[StringLength]属性。 @PaulWhite在此处的答案中提到了列过宽的一些其他可能的负面因素

是的,在任何地方使用varchar(max)都会影响您的性能-请勿这样做!使用适当的数据类型-仅在确实需要超过8000个字符时才使用varchar(max)! (我从未见过这么长的人的名字或电子邮件!)-请参见再使用VARCHAR(n)有什么意义?了解更多信息

@marc_s很棒的链接。我知道它确实会影响性能。当我用SQL定义自己的表时,我使用varchar(n)。我的问题更多是关于它会在多大程度上损害性能(尽管我意识到,并没有明确说明)。

工作链接-不再使用VARCHAR(n)有什么意义?

#1 楼

较大的nvarchar(最大)数据项(超过8000个字节左右)将溢出到文本存储中,并需要其他I / O。较小的项目将存储在行中。有控制此行为的选项-有关更多详细信息,请参见MSDN文章。

如果存储在行中,则不会有明显的I / O性能开销;

但是,将nvarchar(max)列留在不需要它们的数据库周围是很差的形式。它确实有一些性能开销,并且数据大小通常对于理解数据表很有帮助-例如,一个50或100个字符宽的varchar列很可能是描述或自由文本字段,其中(例如)10- 20个字符可能是一个代码。您会惊讶于这样的假设通常常常需要从数据库中推断出多少含义。

在数据仓库中工作(通常在支持不佳或没有文档的遗留系统中使用数据库模式)易于理解的功能非常有价值。如果您认为数据库是应用程序的旧版,请尝试对要从您那里继承数据库的人感到友好。

#2 楼

尽管这不能回答您的特定问题,但可能使您不必首先提出该问题:可以在C#模型类中的字符串变量上设置长度,这将导致Entity Framework生成SQL使用固定长度的nvarchar类型(例如nvarchar(50)),而不是nvarchar(max)

例如,代替:

public string Name { get; set; }


您可以使用:

[StringLength(50)]
public string Name { get; set; }


如果需要,还可以将类型强制为varchar而不是nvarchar,如下所示:

[Column(TypeName = "VARCHAR")]
[StringLength(50)]
public string Name { get; set; }


来源:https://stackoverflow.com/questions/ 7341783 /实体框架数据注释集字符串长度varchar / 7341920

评论


找到这个答案是为了让我弄清楚EF Core支持同时设置类型和长度(varchar(50)),但是EF 6要求此答案中的内容。

–辛加
19年1月25日在22:19

#3 楼

索引最大的问题。来自BOL:


大对象(LOB)数据类型为ntexttext
varchar(max)nvarchar(max)varbinary(max)xmlimage的列不能为
指定为索引的键列。


如果无法正确建立索引,查询将会很慢。从数据完整性的角度来看,拥有nvarchar(max)可以将比指定限制更多的坏数据放入字段中。

#4 楼

是的,将string映射到nvarchar(max)时的默认EF行为不好。在EF 6中,您可以添加自己的自定义约定,以使用自己的首选默认映射覆盖此行为。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Properties<string>()
        .Configure(s => s.HasMaxLength(200).HasColumnType("varchar") );

    base.OnModelCreating(modelBuilder);
}


如上所述覆盖OnModelCreating会将所有字符串的默认映射更改为varchar(200)

评论


这在EF Core 1.0中不起作用

– Shittu Joseph Olugbenga
16年8月15日在11:38

将字符串映射到nvarchar(max)中的默认EF行为不好,这似乎是您的普遍观点。你能解释为什么这不好吗?或者,您认为EF不是需要使用多种语言的业务应用程序框架?因为那是处理数据库上多种语言所需的列类型。

–Matthias Burger
17-2-9在13:21



@MatthiasBurger nvarchar(max)的性能令人恐惧,尤其是在复制环境中。这不是一个普遍的观点,而是众所周知的事实。

–user2966445
17年5月23日在21:11

@ user2966445对不起,我认为这是一个误会:)当然,麦克斯太可怕了。但是,如果您想使用多种语言(以及它们的不同字符集),则需要使用nvarchar,对吗?

–Matthias Burger
17年5月24日在7:53

@MatthiasBurger是的,对不同的字符集使用nvarchar,但是整个文章都是关于性能和字段长度的,而不是使用nvarchar vs. varchar。

–user2966445
17年5月24日在20:31