Денормалізація для підвищення продуктивності? Це звучить переконливо, але це не тримає води.
Кріс Дат, який у компанії з доктором Тедом Коддом був оригінальним прихильником моделі реляційних даних, вичерпав терпіння з неправильно аргументованими аргументами проти нормалізації та систематично їх зносив науковим методом: він отримав великі бази даних і перевірив ці твердження.
Я думаю , що він написав в реляційної базі даних Писання 1988-1991 , але ця книга була пізніше згорнутим в видання шостого Введення в бази даних системи , яка є остаточним текстом по теорії база даних і дизайну, в восьмому виданні , як я пишу і , ймовірно, залишуся у друку на наступні десятиліття. Кріс Дата був експертом у цій галузі, коли більшість із нас ще бігали босоніж.
Він виявив, що:
- Деякі з них стосуються особливих справ
- Усі вони не платять за загальне використання
- Усі вони значно гірші для інших особливих випадків
Все повертається до зменшення розміру робочого набору. Приєднання за допомогою правильно підібраних ключів з правильно встановленими індексами коштує дешево, а не дорого, оскільки вони дозволяють істотно підрізати результат перед матеріалізацією рядків.
Матеріалізація результату передбачає масові читання дисків, які є найдорожчим аспектом вправи на порядок. З іншого боку, виконання з'єднання логічно вимагає пошуку лише клавіш . На практиці навіть не отримано навіть ключових значень: ключові хеш-значення використовуються для порівняння об'єднань, зменшуючи витрати на приєднання кількох стовпців і кардинально зменшуючи вартість з'єднань, що включають порівняння рядків. Мало того, що набагато більше вміститься в кеші, буде набагато менше читання дисків.
Більше того, хороший оптимізатор вибере найбільш обмежувальну умову та застосує її до того, як здійснить приєднання, дуже ефективно використовуючи високу селективність приєднань до індексів з високою кардинальністю.
Безумовно, такий тип оптимізації може бути застосований і до денормалізованих баз даних, але такі люди, які хочуть денормалізувати схему, зазвичай не замислюються про кардинальність, коли (якщо) вони встановлюють індекси.
Важливо розуміти, що сканування таблиць (обстеження кожного рядка в таблиці під час створення з'єднання) на практиці рідкісні. Оптимізатор запитів вибере сканування таблиці лише тоді, коли виконано одне або більше із наведених нижче.
- У співвідношенні менше 200 рядків (у цьому випадку сканування буде дешевшим)
- У стовпцях приєднання немає відповідних індексів (якщо доречно приєднатися до цих стовпців, то чому їх не індексувати? Виправити це)
- Тип примус потрібно до того , як стовпці можна порівняти (WTF?! Виправити його або піти додому) SEE END ПРИМІТКИ ДЛЯ ADO.NET ВИПУСКУ
- Одним із аргументів порівняння є вираз (без індексу)
Виконання операції дорожче, ніж її виконання. Однак виконання неправильної операції, примушування до безглуздого дискового вводу / виводу, а потім викидання дроселя перед виконанням з'єднання вам дійсно потрібно, набагато дорожче. Навіть коли попередньо обчислюється "неправильна" операція та розумно застосовуються індекси, все ще залишається значна пеня. Денормалізація для попереднього обчислення об'єднання - незважаючи на пов'язані з цим аномалії оновлення - є зобов'язанням до певного приєднання. Якщо вам потрібно інше приєднання, це зобов'язання обійдеться вам у велику суму .
Якщо хтось хоче нагадати мені, що це мінливий світ, я думаю, що ви побачите, що більші набори даних про більш грубі апаратні засоби просто перебільшують поширення висновків Дата.
Для всіх вас, хто працює над платіжними системами або генераторами небажаної пошти (ганьба над вами) і з обуренням налаштовуєте руку на клавіатуру, щоб сказати мені, що ви знаєте на той факт, що денормалізація швидша, вибачте, але ви живете в одному із спеціальних випадки - конкретно, випадок, коли ви обробляєте всі дані, в порядку. Це не загальний випадок, і ви будете виправдані в вашої стратегії.
Ви не виправдані фальшивим узагальненням. Див. Кінець розділу приміток для отримання додаткової інформації про належне використання денормалізації в сценаріях зберігання даних.
Я також хотів би відповісти
Приєднання - це лише декартові вироби з деяким блиском
Який вантаж болоків. Обмеження застосовуються якомога раніше, перш за все обмежуючі. Ви читали теорію, але не зрозуміли її. Приєднання трактуються як "декартові продукти, до яких застосовуються предикати" лише оптимізатором запитів. Це символічне подання (фактично нормалізація) для полегшення символьної декомпозиції, щоб оптимізатор міг виробляти всі еквівалентні перетворення та класифікувати їх за вартістю та вибірковістю, щоб він міг вибрати найкращий план запитів.
Єдиний спосіб, коли ви завжди отримаєте оптимізатор для виготовлення декартового продукту, - це не забезпечити присудок: SELECT * FROM A,B
Примітки
Девід Олдрідж надає важливу додаткову інформацію.
Окрім індексів та сканувань таблиць, існує безліч інших стратегій, а сучасний оптимізатор обійдеться їм усім перед тим, як скласти план виконання.
Практична порада: якщо його можна використовувати як зовнішній ключ, то індексуйте його, щоб оптимізатор став доступним для стратегії індексів .
Раніше я був розумнішим за оптимізатор MSSQL. Це змінилося дві версії тому. Зараз це взагалі мене вчить . Це, в дуже реальному сенсі, експертна система, кодифікуючи всю мудрість багатьох дуже розумних людей у достатньо закритій галузі, що система, заснована на правилах, є ефективною.
"Боллоки", можливо, були нетактичними. Мене просять бути менш вибагливим і нагадали, що математика не бреше. Це правда, але не всі наслідки математичних моделей обов'язково слід сприймати буквально. Квадратні корені від’ємних чисел дуже зручні, якщо ви ретельно уникаєте вивчення їх абсурдності (каламбур) і переконуєтесь, що ви скасуєте їх усе, перш ніж спробувати інтерпретувати своє рівняння.
Причиною того, що я відповів настільки жорстоко, було те, що це твердження говорить про це
Приєднання - декартові продукти ...
Це не може бути те , що мав в виду , але це те , що було написано, і це категорично НЕ відповідає дійсності. Декартовий продукт - це відношення. Об'єднання - це функція. Більш конкретно, з'єднання - це функція, що оцінюється відношенням. З порожнім предикатом він створить декартовий продукт, і перевірка того, що це робиться, - це одна перевірка правильності роботи механізму запитів бази даних, але ніхто не пише невпинно приєднується на практиці, оскільки вони не мають практичної цінності поза аудиторією.
Я закликав це, тому що я не хочу, щоб читачі потрапляли в древню пастку плутати модель з річчю, що моделюється. Модель - це наближення, навмисно спрощене для зручного маніпулювання.
Межа для вибору стратегії приєднання до сканування таблиці може відрізнятися між двигунами бази даних. На нього впливає ряд рішень щодо реалізації, таких як коефіцієнт заповнення дерева-вузла, розмір ключового значення та тонкощі алгоритму, але в широкому сенсі високоефективна індексація має час виконання k log n + c . Термін C - це фіксований наклад, який здебільшого складається з часу встановлення, а форма кривої означає, що ви не отримаєте окупності (порівняно з лінійним пошуком), поки n не стане сотнями.
Іноді денормалізація є хорошою ідеєю
Денормалізація - це прихильність до певної стратегії приєднання. Як було сказано раніше, це заважає іншим стратегіям приєднання. Але якщо у вас є відра дискового простору, передбачувані схеми доступу та схильність обробляти багато або все це, то попередньо обчислити об'єднання може бути дуже вартим.
Ви також можете визначити шляхи доступу, які ваша операція зазвичай використовує, і попередньо обчислити всі з'єднання для цих шляхів доступу. Це передумова для сховищ даних, або, принаймні, це тоді, коли їх будують люди, які знають, чому вони роблять те, що роблять, а не лише заради дотримання мовних слів.
Правильно сконструйований сховище даних періодично виробляється об'ємним перетворенням із нормалізованої системи обробки транзакцій. Такий поділ баз даних операцій та звітів надає дуже бажаний ефект усунення зіткнення між OLTP та OLAP (обробка в Інтернеті транзакцій, тобто введення даних, та онлайн-аналітична обробка, тобто звітність).
Важливим моментом тут є те, що крім періодичних оновлень, сховище даних читається лише . Це викликає суперечку з питаннями аномалій оновлення.
Не робіть помилки денормалізації вашої бази даних OLTP (бази даних, в якій відбувається введення даних). Це може бути швидше для запуску рахунків, але якщо ви зробите це, ви отримаєте аномалії оновлення. Ви коли-небудь намагалися отримати Reader's Digest, щоб перестати надсилати вам речі?
Простір на диску сьогодні дешевий, тому вибивайте себе. Але денормалізація - це лише частина історії для сховищ даних. Набагато більший показник підвищення продуктивності отримується від попередньо обчислених зведених значень: щомісячні підсумки, такі речі. Йдеться завжди про зменшення робочого набору.
Проблема ADO.NET з невідповідностями типів
Припустимо, у вас є таблиця SQL Server, що містить індексований стовпець типу varchar, і ви використовуєте AddWithValue для передачі параметра, що обмежує запит у цьому стовпчику. Рядки C # - це Unicode, тому виведений тип параметра буде NVARCHAR, який не відповідає VARCHAR.
VARCHAR до NVARCHAR - це конверсія, що розширюється, і це відбувається неявно - але попрощайтеся з індексуванням і удачі, розробивши чому.
"Порахуйте хіти диска" (Рік Джеймс)
Якщо все запам’ятовано в оперативній пам’яті, JOINs
досить дешево. Тобто за нормалізацію не передбачено особливих штрафних санкцій .
Якщо "нормалізована" схема спричиняє JOINs
удари диска дуже сильно, але еквівалентна "денормалізована" схема не повинна була б потрапляти на диск, тоді денормалізація виграє конкуренцію за продуктивність.
Коментар від оригінального автора: Сучасні двигуни бази даних дуже добре організовують послідовність доступу, щоб мінімізувати пропуски кешу під час операцій приєднання. Вищезазначене, хоча це правда, може бути неправильним, оскільки це означає, що великі дані приєднання обов'язково є досить дорогими. Це призведе до поганого прийняття рішень з боку недосвідчених розробників.