Код EF Спочатку використовує nvarchar (max) для всіх рядків. Чи не зашкодить це виконання запиту?


29

У мене є деякі бази даних, створені спочатку за допомогою Entity Framework Code; програми працюють і взагалі я дуже задоволений тим, що 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 тут
Мартін Сміт

3
Так , використання varchar(max)скрізь шкодить вашій роботі - не робіть цього! Використовуйте відповідні типи даних - використовуйте varchar(max) ТОЛЬКО, якщо ВАМО потрібно більше 8000 символів! (Я ніколи не бачив, щоб ім’я чи електронна пошта людини були такими довгими!) - Дивіться, в чому сенс використання VARCHAR (n) Більше? для отримання додаткової інформації
marc_s

@marc_s Відмінне посилання. Я знаю, що це шкодить продуктивності. Коли я визначаю власні таблиці за допомогою SQL, я використовую varchar (n). Моє запитання було більше про те, наскільки це шкодить продуктивності (хоча я розумію, як розміщено це було не явно).
Нейт

Відповіді:


24

Більш великі nvarchar (максимум) елементи даних (понад 8000 байт або близько того) перейдуть у сховище тексту та потребують додаткових вводу-виводу. Менші елементи зберігатимуться в рядку. Є варіанти, які керують такою поведінкою - детальніше див. Цю статтю MSDN .

Якщо зберігається в рядку, немає значних накладних витрат вводу / виводу; можуть бути додаткові накладні витрати процесора на обробку типу даних, але це, ймовірно, буде незначним.

Однак залишити стовпці nvarchar (max) навколо бази даних там, де вони не потрібні, є досить поганою формою. Він має деяку ефективність роботи та часто розміри даних є дуже корисними для розуміння таблиці даних - наприклад, стовпець varchar шириною 50 або 100 символів, ймовірно, буде описом або полем із вільним текстом, де те, що (скажімо) 10- 20 символів, швидше за все, буде кодом. Ви були б здивовані, скільки сенсу часто доводиться виводити з бази даних через такі припущення.

Робота зі зберіганням даних часто, як не на погано підтримуваних або задокументованих застарілих системах, мати схему баз даних, яку легко зрозуміти, є досить цінною. Якщо ви вважаєте, що база даних є спадщиною програми, постарайтеся бути приємними людям, які збираються успадкувати її від вас.


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:

Стовпці , які мають типів даних великих об'єктів (LOB) 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);
}

Перезапис, OnModelCreatingяк зазначено вище, змінить відображення за замовчуванням для всіх рядків на varchar(200).


1
Це не працює в EF Core 1.0
Shittu Joseph Olugbenga

the default EF behavior in mapping string to nvarchar(max) is not goodце здається вашою узагальненою думкою. Ви можете пояснити, чому це не добре? Або, ви думаєте, EF не є основою для бізнес-додатків, де вам потрібно працювати з декількома мовами? Тому що це потрібний тип стовпця для обробки декількох мов у базі даних.
Маттіас Бургер

1
@MatthiasBurger nvarchar (max) - жахливий для продуктивності, особливо у тираженому середовищі. Це не узагальнена думка, це добре відомий факт.
користувач2966445

@ user2966445 вибачте, я думаю, що сталося непорозуміння :) звичайно, maxжахливо. Але якщо ви хочете працювати з декількома мовами (та різними наборами символів), вам потрібно скористатися, nvarcharчи я помиляюся?
Маттіас Бургер

@MatthiasBurger Правильно, використовуйте nvarchar для різних наборів символів, але вся ця публікація стосується продуктивності та довжини поля, а не використання nvarchar проти varchar.
користувач2966445
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.