EF Kodu Önce tüm dizeler için nvarchar (max) kullanır. Bu sorgu performansını etkiler mi?


29

Önce Entity Framework Code kullanılarak oluşturulan bazı veritabanlarım var; uygulamalar çalışıyor ve genel olarak Kod İlkenin yapmamı sağladığı şeyden oldukça memnunum. Zorunlu olarak önce bir programcı ve bir de DBA saniyesiyim. Veritabanının ne yapmasını istediğimi C # 'da tanımlamak için DataAttributes hakkında okuyorum; ve sorum şu: bu nvarchar(max)ipleri masamda bulundurarak ne ceza alacağım (aşağıdaki örneğe bakın)?

Bu özel tabloda birkaç sütun var; C # 'de şöyle tanımlanırlar:

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

İsim, Kaynak, Üretilmiş ve Yazılı olarak sorgulamayı ve / veya sıralamayı bekliyorum. Ad ve Kaynak'ın 0-50 karakter uzunluğunda, bazen 150'ye kadar olmasını bekliyorum. Bu tablonun oldukça küçük başlamasını (<100k satır), ancak zamanla önemli ölçüde (> 1m satır) büyümesini bekliyorum. Açıkçası, mesaj küçük veya büyük olabilir ve muhtemelen sorgulanmayacaktır.

Bilmek istediğim, Adı ve Kaynak sütunlarımın, nvarchar(max)150 karakterden daha büyük olmalarını asla beklemeyeceğim şekilde tanımlanması gibi bir performans etkisi var mı?


5
Uygulamanız[MaxLength] veya [StringLength]özellikleri uygulamanız gerekiyor gibi görünüyor . Çok geniş sütunların bazı olası olumsuz faktörleri burada @ PaulWhite'nin cevabında belirtilmiştir
Martin Smith

3
EVET , varchar(max)her yeri kullanmak performansınıza zarar verir - yapmayın! Kullanım uygun kullanımını - datatypes varchar(max) SADECE eğer gerçekten fazla 8000 karakter gerekiyor! (Hiç kimsenin adını veya e-postasını o kadar uzun zamandır görmedim!) - Bkz . VARCHAR (n) Artık Kullanmanın Amacı Nedir? daha fazla bilgi için
marc_s

@ marc_s Büyük bağlantı. Performansa zarar verdiğini biliyorum. Kendi tablolarımı SQL ile tanımlarken varchar (n) kullanıyorum. Benim sorum, performansı ne kadar acıttığına dair daha fazla şeydi (açık şekilde net olmadığını belirtti.
Nate

Yanıtlar:


24

Büyük nvarchar (max) veri öğeleri (8000 bayttan fazla) metin deposuna taşar ve ek G / Ç gerektirir. Küçük öğeler sırayla saklanır. Bu davranışı denetleyen seçenekler var - daha fazla ayrıntı için bu MSDN makalesine bakın.

Satırda saklanırsa, genel giderlerde önemli bir G / Ç performansı yoktur; veri türünü işlerken ek CPU ek yükü olabilir, ancak bunun küçük olması muhtemeldir.

Bununla birlikte, nvarchar (max) sütunlarının gerekmediği yerde veritabanının etrafında bırakılması oldukça zayıf bir formdur. Genelde bazı performansa sahiptir ve genellikle veri boyutları veri tablosunu anlamada oldukça yararlıdır - örneğin, 50 veya 100 karakter genişliğinde bir varchar sütunu bir açıklama veya serbest metin alanı olabilir. 20 karakter ling bir kod olabilir. Bunun, genellikle böyle bir varsayımlar yoluyla bir veritabanından ne kadar anlam çıkarması gerektiğine şaşıracaksınız.

Veri depolama alanında çalışmak, çoğu zaman zayıf desteklenmiş veya belgelenmiş eski sistemlerde olmadığı gibi, anlaşılması kolay bir veritabanı şemasına sahip olmak oldukça değerlidir. Veritabanını uygulamanın mirası olarak görüyorsanız, sizden devralacak kişilere iyi davranmaya çalışın.


18

Bu, kendi sorunuza cevap vermese de, soruyu ilk etapta sormanıza gerek kalmamasını engelleyebilir: C # model sınıfınızdaki string değişkenlerinize bir uzunluk koymak mümkündür; bu, Entity Framework'ün SQL üretmesine neden olur nvarchar(50)bunun yerine sabit uzunlukta bir nvarchar türü (örn. ) kullanır nvarchar(max).

Örneğin, yerine:

public string Name { get; set; }

Kullanabilirsiniz:

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

İsterseniz, türün varcharyerine nvarcharistenirse aşağıdaki gibi olmasını da zorlayabilirsiniz :

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

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


2
EF Core'un aynı anda hem ayar hem de uzunluk ayarını desteklediğini varchar(50)bulmam için bu cevabı bulmam gerekiyor ( ), ancak EF 6 bu cevabın içinde ne olduğunu gerektiriyor.
Sinjai

9

En büyük endişenin endekslenmesi. BOL’dan:

Büyük nesne (LOB) veri türleri olan sütunlar ntext, text, varchar(max), nvarchar(max), varbinary(max), xml, ya da imagebir dizin için önemli sütunlar olarak belirtilemez.

Düzgün bir şekilde endeksleyemiyorsanız, yavaş sorgularınız olacaktır. Ve veri bütünlüğü perspektifinden bakıldığında, nvarchar(max)sınırın belirtildiğinden daha fazla alana hatalı veri koyulmasına izin verilmesi.


9

Evet, haritalama varsayılan EF davranış stringiçin nvarchar(max)iyi değil. EF 6'da, bu davranışı kendi tercih ettiğiniz varsayılan haritalama ile geçersiz kılmak için kendi özel kurallarınızı ekleyebilirsiniz.

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

    base.OnModelCreating(modelBuilder);
}

OnModelCreatingYukarıdaki gibi geçersiz kılma , tüm dizelerin varsayılan eşlemesini olarak değiştirir varchar(200).


1
Bu, EF Core 1.0'da çalışmıyor
Shittu Joseph Olugbenga,

the default EF behavior in mapping string to nvarchar(max) is not goodbu sizin genel görüşünüz gibi görünüyor. Bunun neden iyi olmadığını açıklayabilir misiniz? Veya, EF'nin birden fazla dilde çalışmanız gereken iş uygulamaları için bir çerçeve olmadığını mı düşünüyorsunuz? Çünkü bu, veritabanındaki birden fazla dili işlemek için istenen sütun türüdür.
Matthias Burger,

1
@MatthiasBurger nvarchar (max), özellikle çoğaltılmış bir ortamda, performans için korkunç. Bu genel bir görüş değil, iyi bilinen bir gerçektir.
user2966445

@ user2966445 üzgünüm, bir yanlış anlaşılma olduğunu düşünüyorum :) elbette, maxkorkunç. Fakat birden fazla dili (ve farklı karakter setlerini) ele almak istiyorsanız, nvarcharyanlış mı kullanmam gerekiyor ?
Matthias Burger

@MatthiasBurger Bu doğru, farklı karakter kümeleri için nvarchar kullanın, ancak bu yazının tamamı nvarchar ve varchar kullanımıyla değil, performans ve alan uzunluklarıyla ilgilidir.
user2966445
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.