EF Code First menggunakan nvarchar (maks) untuk semua string. Apakah ini akan mengganggu kinerja kueri?

29

Saya memiliki beberapa database yang dibuat menggunakan Entity Framework Code First; aplikasi bekerja dan secara umum saya cukup senang dengan apa yang pertama kali saya lakukan dengan Code. Saya seorang programmer pertama, dan DBA kedua, karena kebutuhan. Saya membaca tentang DataAttributes untuk menjelaskan lebih lanjut dalam C # apa yang saya ingin database lakukan; dan pertanyaan saya adalah: hukuman apa yang akan saya makan dengan memasukkan nvarchar(max)string ini di meja saya (lihat contoh di bawah)?

Ada beberapa kolom dalam tabel khusus ini; di C # mereka didefinisikan sebagai:

    [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; }

Saya berharap untuk meminta dan / atau mengurutkan berdasarkan Nama, Sumber, Dihasilkan, dan Ditulis. Saya berharap Nama dan Sumber berada dalam panjang karakter 0-50, kadang-kadang hingga 150. Saya berharap tabel ini mulai cukup kecil (<100r baris), tetapi tumbuh secara signifikan dari waktu ke waktu (> 1jej baris). Jelas pesan bisa kecil atau besar, dan mungkin tidak akan dipertanyakan.

Yang ingin saya ketahui, apakah ada hit kinerja untuk kolom Nama dan Sumber saya didefinisikan sebagai nvarchar(max)ketika saya tidak pernah berharap mereka lebih besar dari 150 karakter?

Nate
sumber
5
Sepertinya Anda perlu menerapkan salah satu [MaxLength]atau [StringLength]atribut. Beberapa kemungkinan faktor negatif tambahan dari kolom yang
Martin Smith
3
YA , menggunakan di varchar(max)mana - mana akan merusak kinerja Anda - jangan lakukan itu! Gunakan tipe data yang sesuai - varchar(max) HANYA SAJA jika Anda BENAR - BENAR membutuhkan lebih dari 8000 karakter! (Saya belum pernah melihat nama atau email seseorang selama itu!) - Lihat Apa gunanya Menggunakan VARCHAR (n) Lagi? untuk info lebih lanjut
marc_s
@marc_s Tautan bagus. Saya tahu itu merusak kinerja. Ketika saya mendefinisikan tabel saya sendiri dengan SQL saya menggunakan varchar (n). Pertanyaan saya adalah lebih banyak tentang seberapa banyak itu menyakiti kinerja (meskipun saya menyadari sebagai diposting yang tidak jelas secara eksplisit).
Nate
Tautan yang berfungsi - Apa gunanya Menggunakan VARCHAR (n) Lagi?
GFoley83

Jawaban:

24

Item data nvarchar (max) yang lebih besar (lebih dari 8000 byte atau lebih) akan tumpah ke penyimpanan teks dan membutuhkan I / O tambahan. Item yang lebih kecil akan disimpan secara berturut-turut. Ada opsi yang mengontrol perilaku ini - lihat artikel MSDN ini untuk detail lebih lanjut.

Jika disimpan dalam baris tidak ada overhead kinerja I / O yang signifikan; mungkin ada overhead CPU tambahan pada pemrosesan tipe data tetapi ini kemungkinan kecil.

Namun, meninggalkan kolom nvarchar (maks) di sekitar database di mana mereka tidak diperlukan adalah bentuk yang agak buruk. Itu memang memiliki beberapa overhead kinerja dan seringkali ukuran data cukup membantu dalam memahami tabel data - misalnya, kolom varchar lebar 50 atau 100 karakter cenderung menjadi deskripsi atau bidang teks bebas di mana satu itu (katakanlah) 10- 20 karakter mungkin merupakan kode. Anda akan terkejut betapa banyak makna yang harus disimpulkan dari sebuah database melalui asumsi seperti ini.

Bekerja di pergudangan data, sesering mungkin tidak pada sistem legacy yang kurang didukung atau terdokumentasi, memiliki skema database yang mudah dipahami cukup berharga. Jika Anda menganggap database sebagai warisan aplikasi, cobalah bersikap baik kepada orang-orang yang akan mewarisinya dari Anda.

ConcernedOfTunbridgeWells
sumber
18

Meskipun ini tidak menjawab pertanyaan spesifik Anda, ini mungkin menghalangi Anda dari perlu untuk mengajukan pertanyaan di tempat pertama: Dimungkinkan untuk menetapkan panjang pada variabel string Anda di kelas model C # Anda, yang akan menyebabkan Entity Framework untuk menghasilkan SQL yang menggunakan tipe nvarchar dengan panjang tetap (misalnya nvarchar(50)), bukan nvarchar(max).

Misalnya, alih-alih:

public string Name { get; set; }

Anda dapat gunakan:

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

Anda juga bisa memaksakan tipe menjadi varcharbukan nvarchar, jika diinginkan, sebagai berikut:

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

Sumber: https://stackoverflow.com/questions/7341783/entity-framework-data-annotations-set-stringlength-varchar/7341920

Jon Schneider
sumber
2
Perlu menemukan jawaban ini untuk membiarkan saya mengetahui bahwa EF Core mendukung tipe dan panjang pengaturan pada waktu yang sama ( varchar(50)), tetapi EF 6 membutuhkan apa yang ada di jawaban ini.
Sinjai
9

Pengindeksan menjadi perhatian terbesar. Dari BOL:

Kolom yang dari tipe data objek besar (LOB) ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, atau imagetidak dapat ditetapkan sebagai kolom kunci untuk indeks.

Jika Anda tidak dapat mengindeks dengan benar, Anda akan memiliki pertanyaan lambat. Dan dari perspektif integritas data, memiliki nvarchar(max)akan memungkinkan lebih banyak data buruk dimasukkan ke dalam bidang daripada menentukan batasnya.

HLGEM
sumber
9

Ya, perilaku EF default dalam pemetaan stringke nvarchar(max)tidak baik. Di EF 6 Anda dapat menambahkan konvensi kustom Anda sendiri untuk mengesampingkan perilaku ini dengan pemetaan default pilihan Anda sendiri.

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

    base.OnModelCreating(modelBuilder);
}

Mengesampingkan OnModelCreatingseperti di atas akan mengubah pemetaan default untuk semua string varchar(200).

Paul
sumber
1
Ini tidak berfungsi di EF Core 1.0
Shittu Joseph Olugbenga
the default EF behavior in mapping string to nvarchar(max) is not goodini tampaknya menjadi pendapat umum Anda. dapatkah Anda menjelaskan mengapa ini tidak baik? Atau, Anda pikir, EF bukan kerangka kerja untuk aplikasi bisnis di mana Anda perlu bekerja dengan berbagai bahasa? Karena itulah tipe kolom yang diinginkan untuk menangani banyak bahasa pada basis data.
Matthias Burger
1
@MatthiasBurger nvarchar (maks) mengerikan untuk kinerja, terutama di lingkungan yang direplikasi. Itu bukan pendapat umum, itu fakta yang sudah diketahui.
user2966445
@ user2966445 maaf, saya pikir ada kesalahpahaman :) pasti maxmengerikan. Tetapi jika Anda ingin menangani beberapa bahasa (dan karakter yang berbeda) Anda perlu menggunakan nvarcharapakah saya salah?
Matthias Burger
@MatthiasBurger Itu benar, gunakan nvarchar untuk karakter yang berbeda, tetapi seluruh posting ini adalah tentang kinerja dan panjang bidang, bukan penggunaan nvarchar vs varchar.
user2966445