Денормализация для улучшения производительности? Звучит убедительно, но не выдерживает критики.
Крис Дэйт, который в компании с доктором Тедом Коддом был первоначальным сторонником реляционной модели данных, потерял терпение с помощью дезинформированных аргументов против нормализации и систематически уничтожал их, используя научный метод: он получил большие базы данных и проверил эти утверждения.
Я думаю , что он написал в реляционной базе данных Писаний 1988-1991 , но эта книга была позже свернутым в издание шестого Введения в базы данных системы , которая является окончательным текстом по теории база данных и дизайну, в восьмом издании , как я пишу и , вероятно, останусь в печати на десятилетия вперед. Крис Дэйт был экспертом в этой области, когда большинство из нас все еще бегали босиком.
Он обнаружил, что:
- Некоторые из них держатся для особых случаев
- Все они не в состоянии расплатиться за общее использование
- Все они значительно хуже для других особых случаев.
Все сводится к уменьшению размера рабочего набора. Объединения, включающие правильно выбранные ключи с правильно настроенными индексами, дешевы, не дороги, потому что они позволяют значительно сократить результат до материализации строк.
Материализация результата включает в себя массовые чтения с диска, которые на порядок являются самым дорогим аспектом упражнения. Выполнение объединения, напротив, логически требует извлечения только ключей . На практике даже ключевые значения не извлекаются: ключевые хэш-значения используются для сравнений соединений, что снижает стоимость объединений с несколькими столбцами и радикально снижает стоимость объединений, связанных со сравнениями строк. Мало того, что он будет гораздо больше вписываться в кеш, там гораздо меньше чтения с диска.
Более того, хороший оптимизатор выберет наиболее ограничивающее условие и применит его перед выполнением объединения, очень эффективно используя высокую селективность объединений для индексов с высокой мощностью.
По общему признанию этот тип оптимизации может также применяться к денормализованным базам данных, но люди, которые хотят денормализовать схему, обычно не думают о количестве элементов, когда (если) они устанавливают индексы.
Важно понимать, что сканирование таблицы (проверка каждой строки таблицы в процессе создания соединения) на практике встречается редко. Оптимизатор запросов будет выбирать сканирование таблицы только тогда, когда выполняется одно или несколько из следующих действий.
- В отношении менее 200 строк (в этом случае сканирование будет дешевле)
- Нет подходящих индексов для столбцов соединения (если имеет смысл объединить эти столбцы, то почему они не проиндексированы? Исправить это)
- Приведение типов требуется перед сравнением столбцов (WTF ?! исправить это или вернуться домой) СМ. КОНЕЧНЫЕ ЗАМЕЧАНИЯ ПО ПРОБЛЕМЕ ADO.NET
- Одним из аргументов сравнения является выражение (без индекса)
Выполнение операции обходится дороже, чем ее отсутствие. Однако выполнение неправильной операции, принудительное выполнение бессмысленного дискового ввода-вывода, а затем отбрасывание шлака перед выполнением действительно необходимого объединения, намного дороже. Даже когда «неправильная» операция предварительно вычислена и индексы были разумно применены, остается значительный штраф. Денормализация предварительного вычисления объединения - несмотря на связанные с этим аномалии обновления - является обязательством для конкретного объединения. Если вам нужен РАЗЛИЧНЫХ присоединиться, что обязательство будет стоить вам большой .
Если кто-то захочет напомнить мне, что это изменчивый мир, я думаю, вы обнаружите, что большие наборы данных на более жестком оборудовании только преувеличивают распространение результатов Date.
Для всех вас, кто работает над биллинговыми системами или генераторами нежелательной почты (как вам не стыдно) и возмущенно протягивает руку к клавиатуре, чтобы сказать мне, что вы точно знаете, что денормализация происходит быстрее, извините, но вы живете в одном из специальных случаи - в частности, случай, когда вы обрабатываете все данные по порядку. Это не общий случай, и вы будете оправданы в вашей стратегии.
Вы не вправе ложно обобщать это. См. Конец раздела примечаний для получения дополнительной информации о надлежащем использовании денормализации в сценариях хранилищ данных.
Я также хотел бы ответить на
Соединения - это просто декартовы произведения с блеском для губ
Что за бред Ограничения применяются как можно раньше, в первую очередь наиболее ограничительные. Вы читали теорию, но не поняли ее. Объединения рассматриваются как «декартовы произведения, к которым применяются предикаты» только оптимизатором запросов. Это символическое представление (фактически нормализация) для облегчения символической декомпозиции, чтобы оптимизатор мог произвести все эквивалентные преобразования и ранжировать их по стоимости и селективности, чтобы он мог выбрать лучший план запроса.
Единственный способ получить оптимизатор для создания декартового продукта - это не указывать предикат: 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
к частому попаданию на диск, но эквивалентная «денормализованная» схема не должна была бы попадать на диск, то денормализация побеждает в конкуренции за производительность.
Комментарий от оригинального автора: современные движки баз данных очень хороши в организации последовательности доступа, чтобы минимизировать пропуски кэша во время операций соединения. Вышеприведенное, хотя и верно, может быть неверно истолковано, поскольку подразумевает, что объединение обязательно проблематично дорого для больших данных. Это привело бы к плохому принятию решений со стороны неопытных разработчиков.