EF Code First ใช้ nvarchar (สูงสุด) สำหรับสตริงทั้งหมด สิ่งนี้จะทำให้ประสิทธิภาพการค้นหาเสียหายหรือไม่


29

ฉันมีฐานข้อมูลบางส่วนที่สร้างขึ้นโดยใช้รหัสเอนทิตีกรอบแรก; แอพใช้งานได้และโดยทั่วไปฉันมีความสุขมากกับสิ่งที่ 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 แถว) แต่จะเติบโตอย่างมีนัยสำคัญเมื่อเวลาผ่านไป (> 1 ม. แถว) ข้อความที่เห็นได้ชัดอาจมีขนาดเล็กหรือใหญ่และอาจไม่ถูกสอบถาม

สิ่งที่ฉันต้องการทราบมีการกำหนดประสิทธิภาพสำหรับคอลัมน์ชื่อและแหล่งที่มาของฉันถูกกำหนดเป็นnvarchar(max)เมื่อฉันไม่เคยคาดหวังว่าพวกเขาจะมีขนาดใหญ่กว่า 150 อักขระหรือไม่


5
ดูเหมือนว่าคุณต้องใช้อย่างใดอย่างหนึ่ง[MaxLength]หรือ[StringLength]คุณลักษณะ ปัจจัยเชิงลบที่เป็นไปได้เพิ่มเติมของคอลัมน์ที่กว้างเกินไปถูกกล่าวถึงในคำตอบของ @ PaulWhite ที่นี่
Martin Smith

3
ใช่การใช้varchar(max)ทุกที่จะทำให้การแสดงของคุณเจ็บปวด - อย่าทำอย่างนั้น! ใช้ที่เหมาะสมประเภทข้อมูล - การใช้งานvarchar(max) เฉพาะถ้าคุณจริงๆต้องมากกว่า 8000 ตัวละคร! (ฉันไม่เคยเห็นชื่อบุคคลหรืออีเมลมานานขนาดนั้น!) - ดูว่าอะไรคือจุดประสงค์ของการใช้ VARCHAR (n) Anymore? สำหรับข้อมูลเพิ่มเติม
marc_s

@marc_s ลิงค์ที่ยอดเยี่ยม ฉันรู้ว่ามันเจ็บประสิทธิภาพ เมื่อฉันกำหนดตารางของตัวเองด้วย SQL ฉันใช้ varchar (n) คำถามของฉันเกี่ยวกับว่ามันเจ็บมากประสิทธิภาพ (แม้ว่าฉันรู้ว่าโพสต์ที่ไม่ชัดเจนชัดเจน)
เนท

คำตอบ:


24

ไอเท็มข้อมูล nvarchar ขนาดใหญ่ (สูงสุด) (มากกว่า 8000 ไบต์หรือมากกว่านั้น) จะหกลงในที่จัดเก็บข้อความและต้องการ I / O เพิ่มเติม รายการขนาดเล็กจะถูกจัดเก็บในแถว มีตัวเลือกที่ควบคุมพฤติกรรมนี้ - ดูบทความ MSDN นี้สำหรับรายละเอียดเพิ่มเติม

หากเก็บไว้ในแถวจะไม่มีค่าใช้จ่าย I / O ที่มีนัยสำคัญ อาจมีโอเวอร์เฮดของ CPU เพิ่มเติมในการประมวลผลชนิดข้อมูล แต่มีแนวโน้มที่จะน้อย

อย่างไรก็ตามการทิ้งคอลัมน์ nvarchar (สูงสุด) ไว้รอบ ๆ ฐานข้อมูลที่ไม่ต้องการนั้นเป็นรูปแบบที่ค่อนข้างแย่ มันมีค่าใช้จ่ายประสิทธิภาพบางอย่างและบ่อยครั้งที่ขนาดข้อมูลมีประโยชน์มากในการทำความเข้าใจตารางข้อมูล - ตัวอย่างเช่นคอลัมน์ varchar 50 หรือ 100 ตัวอักษรกว้างน่าจะเป็นคำอธิบายหรือเขตข้อมูลข้อความอิสระที่หนึ่ง (พูด) 10 20 ching ling น่าจะเป็นรหัส คุณจะประหลาดใจว่าความหมายที่บ่อยครั้งมีการอนุมานจากฐานข้อมูลผ่านสมมติฐานเช่นนี้

ทำงานในคลังข้อมูลบ่อยครั้งที่ไม่ได้อยู่ในระบบที่ได้รับการสนับสนุนหรือมีเอกสารที่ไม่ดีการมีคีมาฐานข้อมูลที่เข้าใจง่ายนั้นมีค่ามาก หากคุณคิดว่าฐานข้อมูลเป็นมรดกของแอปพลิเคชันลองทำตัวดีกับคนที่จะสืบทอดมันมาจากคุณ


18

แม้ว่าสิ่งนี้จะไม่ตอบคำถามของคุณ แต่ก็อาจขัดขวางคุณไม่ให้ถามคำถามในตอนแรก: เป็นไปได้ที่จะกำหนดความยาวของตัวแปรสตริงของคุณในคลาสโมเดล 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/entity-framework-data-annotations-set-stringlength-varchar/7341920


2
หาคำตอบนี้เพื่อให้ฉันเข้าใจว่า EF Core รองรับประเภทการตั้งค่าและความยาวพร้อมกัน ( varchar(50)) แต่ EF 6 ต้องการสิ่งที่อยู่ในคำตอบนี้
สินใจ

9

การจัดทำดัชนีความกังวลที่ใหญ่ที่สุด จาก BOL:

คอลัมน์ที่เป็นของวัตถุขนาดใหญ่ (ลอบ) ชนิดข้อมูลntext, text, varchar(max), nvarchar(max), varbinary(max), xmlหรือimageไม่สามารถระบุเป็นคอลัมน์ที่สำคัญสำหรับดัชนี

หากคุณทำดัชนีไม่ถูกต้องคุณจะมีข้อความค้นหาช้า และจากมุมมองความสมบูรณ์ของข้อมูลการมีnvarchar(max)จะทำให้ข้อมูลที่ไม่ถูกต้องถูกใส่ในฟิลด์มากกว่าการระบุขีด จำกัด จะเป็น


9

ใช่พฤติกรรมเริ่มต้นของ EF ในการทำแผนที่stringถึงnvarchar(max)ไม่ดี ใน EF 6 คุณสามารถเพิ่มการประชุมที่กำหนดเองของคุณเองเพื่อแทนที่พฤติกรรมนี้ด้วยการแมปเริ่มต้นที่คุณต้องการ

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

    base.OnModelCreating(modelBuilder);
}

เอาชนะดังกล่าวจะมีการเปลี่ยนแปลงการทำแผนที่เริ่มต้นสำหรับสตริงทั้งหมดเพื่อ OnModelCreatingvarchar(200)


1
สิ่งนี้ไม่สามารถใช้ได้ใน EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodนี่เป็นความเห็นทั่วไปของคุณ คุณช่วยอธิบายได้ไหมว่าทำไมสิ่งนี้ถึงไม่ดี หรือคุณคิดว่า EF ไม่ใช่กรอบสำหรับแอปพลิเคชั่นธุรกิจที่คุณต้องใช้กับหลายภาษา? เนื่องจากเป็นคอลัมน์ประเภทที่ต้องการสำหรับจัดการหลายภาษาในฐานข้อมูล
Matthias Burger

1
@MatthiasBurger nvarchar (สูงสุด) น่ากลัวสำหรับประสิทธิภาพโดยเฉพาะอย่างยิ่งในสภาพแวดล้อมที่จำลองแบบ มันไม่ได้เป็นความเห็นทั่วไปมันเป็นความจริงที่รู้จักกันดี
user2966445

@ user2966445 ขออภัยฉันคิดว่ามีความเข้าใจผิด :) แน่นอนว่าmaxน่ากลัว แต่ถ้าคุณต้องการจัดการหลายภาษา (และชุดอักขระที่แตกต่างกัน) คุณจำเป็นต้องใช้nvarcharฉันผิดหรือเปล่า?
Matthias Burger

@MatthiasBurger ถูกต้องใช้ nvarchar สำหรับชุดอักขระที่แตกต่างกัน แต่โพสต์ทั้งหมดนี้เกี่ยวกับประสิทธิภาพและความยาวของฟิลด์ไม่ใช่การใช้ nvarchar vs. varchar
2966445
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.