web-dev-qa-db-ja.com

EF Code Firstは、すべての文字列にnvarchar(max)を使用します。これによりクエリのパフォーマンスが低下しますか?

Entity Framework Code Firstを使用して作成されたデータベースがいくつかあります。アプリは機能しており、一般に、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; }
_

Name、Source、Generated、Writtenに基づいてクエリやソートを行うことを期待しています。名前とソースは0から50文字の長さであり、時々最大150です。このテーブルはかなり小さい(10万行未満)から始まりますが、時間の経過とともに大きくなります(100万行を超える)。明らかに、メッセージは小さい場合と大きい場合があり、おそらく照会されません。

私が知りたいのは、名前とソースの列が150文字を超えることを期待していないときに、nvarchar(max)として定義されている私の列とソースの列にパフォーマンスヒットがあるのでしょうか。

29
Nate

より大きなnvarchar(最大)データ項目(8000バイト以上)はテキストストレージに溢れ、追加のI/Oが必要になります。小さいアイテムは列に格納されます。この動作を制御するオプションがあります-詳細については、この MSDNの記事 を参照してください。

行に格納されている場合、I/Oパフォーマンスのオーバーヘッドはほとんどありません。データ型の処理に追加のCPUオーバーヘッドが発生する可能性がありますが、これはわずかなものである可能性があります。

ただし、nvarchar(最大)列を必要のない場所にデータベースの周りに置いておくのは、かなり貧弱な形式です。 パフォーマンスオーバーヘッド があり、多くの場合、データサイズはデータテーブルを理解するのに非常に役立ちます。たとえば、幅50または100文字のvarchar列は、説明またはフリーテキストフィールドである可能性があります。 (たとえば)10〜20文字のコードはおそらくコードです。このような仮定からデータベースから推測しなければならないことの多い意味に驚くでしょう。

十分にサポートされていないか、文書化されているレガシーシステムではなく、データウェアハウジングで作業することは、理解しやすいデータベーススキーマを持つことは非常に価値があります。データベースをアプリケーションのレガシーと考える場合は、データベースを継承する人にとってはいいものにしてください。

これは特定の質問に答えるものではありませんが、そもそも質問をする必要がなくなる可能性があります。C#モデルクラスの文字列変数に長さを設定することが可能です。これにより、Entity FrameworkがSQLを生成します。 nvarchar(50)ではなく、固定長のnvarchar型(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/entity-framework-data-annotations-set-stringlength-varchar/734192

18
Jon Schneider

最大の懸念事項を索引付けします。 BOLから:

ラージオブジェクト(LOB)データ型の列ntexttextvarchar(max)nvarchar(max)varbinary(max)xml、またはimageは、インデックスのキー列として指定できません。

適切にインデックスを作成できないと、クエリが遅くなります。また、データの整合性の観点から、nvarchar(max)を使用すると、制限を指定するよりも多くの不良データをフィールドに入力できます。

9
HLGEM

はい、stringnvarchar(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)に変更されます。

9
Paul