Я провожу исследование баз данных и смотрю на некоторые ограничения реляционных БД.
Я получаю, что объединения больших таблиц очень дорого, но я не совсем уверен, почему. Что нужно сделать СУБД для выполнения операции соединения, где узкое место?
Как денормализация может помочь преодолеть эти расходы? Как помогают другие методы оптимизации (например, индексация)?
Личные впечатления приветствуются! Если вы собираетесь размещать ссылки на ресурсы, пожалуйста, избегайте Википедии. Я уже знаю, где это найти.
В связи с этим меня интересует денормализованный подход, используемый базами данных облачных сервисов, такими как BigTable и SimpleDB. Смотрите этот вопрос .
FOREGIN KEY
FFS) стал (и остается) самой популярной в мире "R" СУБД, когда у нее была конкуренция со стороны PostgreSQL (без родной версии Windows) и Firebird (фиаско Opensourcing) или даже SQLite?Ответы:
Денормализация для улучшения производительности? Звучит убедительно, но не выдерживает критики.
Крис Дэйт, который в компании с доктором Тедом Коддом был первоначальным сторонником реляционной модели данных, потерял терпение с помощью дезинформированных аргументов против нормализации и систематически уничтожал их, используя научный метод: он получил большие базы данных и проверил эти утверждения.
Я думаю , что он написал в реляционной базе данных Писаний 1988-1991 , но эта книга была позже свернутым в издание шестого Введения в базы данных системы , которая является окончательным текстом по теории база данных и дизайну, в восьмом издании , как я пишу и , вероятно, останусь в печати на десятилетия вперед. Крис Дэйт был экспертом в этой области, когда большинство из нас все еще бегали босиком.
Он обнаружил, что:
Все сводится к уменьшению размера рабочего набора. Объединения, включающие правильно выбранные ключи с правильно настроенными индексами, дешевы, не дороги, потому что они позволяют значительно сократить результат до материализации строк.
Материализация результата включает в себя массовые чтения с диска, которые на порядок являются самым дорогим аспектом упражнения. Выполнение объединения, напротив, логически требует извлечения только ключей . На практике даже ключевые значения не извлекаются: ключевые хэш-значения используются для сравнений соединений, что снижает стоимость объединений с несколькими столбцами и радикально снижает стоимость объединений, связанных со сравнениями строк. Мало того, что он будет гораздо больше вписываться в кеш, там гораздо меньше чтения с диска.
Более того, хороший оптимизатор выберет наиболее ограничивающее условие и применит его перед выполнением объединения, очень эффективно используя высокую селективность объединений для индексов с высокой мощностью.
По общему признанию этот тип оптимизации может также применяться к денормализованным базам данных, но люди, которые хотят денормализовать схему, обычно не думают о количестве элементов, когда (если) они устанавливают индексы.
Важно понимать, что сканирование таблицы (проверка каждой строки таблицы в процессе создания соединения) на практике встречается редко. Оптимизатор запросов будет выбирать сканирование таблицы только тогда, когда выполняется одно или несколько из следующих действий.
Выполнение операции обходится дороже, чем ее отсутствие. Однако выполнение неправильной операции, принудительное выполнение бессмысленного дискового ввода-вывода, а затем отбрасывание шлака перед выполнением действительно необходимого объединения, намного дороже. Даже когда «неправильная» операция предварительно вычислена и индексы были разумно применены, остается значительный штраф. Денормализация предварительного вычисления объединения - несмотря на связанные с этим аномалии обновления - является обязательством для конкретного объединения. Если вам нужен РАЗЛИЧНЫХ присоединиться, что обязательство будет стоить вам большой .
Если кто-то захочет напомнить мне, что это изменчивый мир, я думаю, вы обнаружите, что большие наборы данных на более жестком оборудовании только преувеличивают распространение результатов 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
к частому попаданию на диск, но эквивалентная «денормализованная» схема не должна была бы попадать на диск, то денормализация побеждает в конкуренции за производительность.источник
Большинство комментаторов не замечают широкого спектра методологий соединения, доступных в сложных СУБД, а денормализаторы неизменно затушевывают более высокую стоимость обслуживания денормализованных данных. Не каждое объединение основано на индексах, и в базах данных есть много оптимизированных алгоритмов и методологий для объединения, которые предназначены для снижения затрат на объединение.
В любом случае стоимость объединения зависит от его типа и нескольких других факторов. Это не должно быть дорогим вообще - некоторые примеры.
Базы данных предназначены для объединения, и они очень гибки в том, как они это делают, и, как правило, очень производительны, если не используют механизм объединения неправильно.
источник
Я думаю, что весь вопрос основан на ложной предпосылке. Соединения на больших столах не обязательно дороги. Фактически, эффективное объединение является одной из основных причин существования реляционных баз данных . Соединения на больших наборах часто дороги, но очень редко вы хотите объединить все содержимое большой таблицы A со всем содержимым большой таблицы B. Вместо этого вы пишете запрос так, что используются только важные строки каждой таблицы, и фактический набор, сохраняемый соединением, остается меньшим.
Кроме того, у вас есть эффективность, упомянутая Питером Воне, так что только важные части каждой записи должны храниться в памяти, пока не будет получен окончательный набор результатов. Кроме того, в больших запросах с большим количеством объединений обычно требуется начинать с небольших наборов таблиц и переходить к большим, чтобы набор, сохраняемый в памяти, оставался как можно меньшим как можно дольше.
Если все сделано правильно, объединения, как правило, являются лучшим способом для сравнения, объединения или фильтрации больших объемов данных.
источник
Узким местом является почти всегда дисковый ввод-вывод и, более конкретно, случайный дисковый ввод-вывод (для сравнения, последовательное чтение выполняется довольно быстро и может кэшироваться с помощью стратегий опережающего чтения).
Объединения могут увеличить количество случайных поисков - если вы прыгаете, читая маленькие части большого стола. Но оптимизаторы запросов ищут это и превращают в последовательное сканирование таблицы (отбрасывая ненужные строки), если считают, что так будет лучше.
Одиночная денормализованная таблица имеет аналогичную проблему - строки большие и поэтому меньше помещаются на одной странице данных. Если вам нужны строки, расположенные далеко друг от друга (а большой размер строки делает их дальше друг от друга), то у вас будет больше случайных операций ввода-вывода. Опять же, сканирование таблицы может быть вынуждено избежать этого. Но на этот раз при сканировании таблицы необходимо прочитать больше данных из-за большого размера строки. Добавьте к этому тот факт, что вы копируете данные из одного места в несколько мест, и СУБД имеет гораздо больше информации для чтения (и кеширования).
С 2 таблицами вы также получаете 2 кластеризованных индекса - и, как правило, можете индексировать больше (из-за меньших накладных расходов на вставку / обновление), что может значительно повысить производительность (в основном, опять же, поскольку индексы (относительно) малы, быстро считываются с диска). (или дешево для кэширования), и уменьшите количество строк таблицы, которые вам нужно прочитать с диска).
Единственное, что связано с объединением - это выяснение соответствия строк. Sql Server использует 3 различных типа объединений, в основном на основе размеров наборов данных, для поиска подходящих строк. Если оптимизатор выбирает неправильный тип соединения (из-за неточной статистики, неадекватных индексов или просто ошибки оптимизатора или крайнего случая), это может существенно повлиять на время запроса.
В оптимальном случае они не вызывают дискового ввода-вывода и поэтому незначительны с точки зрения производительности.
В общем, в худшем случае - на самом деле должно быть быстрее считывать такое же количество логических данных из x соединенных таблиц, как и из одной денормализованной таблицы из-за меньшего числа операций чтения с диска. Для чтения того же объема физических данных могут потребоваться небольшие накладные расходы.
Поскольку время запроса обычно определяется затратами на ввод-вывод, а размер ваших данных не изменяется (за вычетом незначительных накладных расходов на строки) при денормализации, не будет огромных преимуществ, если объединить таблицы вместе. Тип денормализации, который имеет тенденцию повышать производительность, IME, заключается в кэшировании вычисленных значений вместо чтения 10000 строк, необходимых для их вычисления.
источник
Порядок, в котором вы присоединяетесь к столам, чрезвычайно важен. Если у вас есть два набора данных, попробуйте построить запрос таким образом, чтобы сначала использовался наименьший из них, чтобы уменьшить объем данных, с которыми должен работать запрос.
Для некоторых баз данных это не имеет значения, например, MS SQL большую часть времени знает правильный порядок соединения. Для некоторых (например, IBM Informix) порядок имеет все значение.
источник
Принятие решения о денормализации или нормализации является довольно простым процессом, если учесть класс сложности объединения. Например, я склонен проектировать свои базы данных с нормализацией, когда запросы O (k log n), где k относительно желаемой выходной величины.
Простой способ денормализовать и оптимизировать производительность - подумать о том, как изменения в вашей нормализованной структуре влияют на вашу денормализованную структуру. Однако это может быть проблематично, поскольку для работы с денормализованной структурой может потребоваться транзакционная логика.
Спор о нормализации и денормализации не закончится, поскольку проблемы огромны. Есть много проблем, где естественное решение требует обоих подходов.
Как правило, я всегда сохранял нормализованную структуру и денормализованные кэши, которые можно восстановить. В конце концов, эти кеши спасают мою задницу, чтобы решить будущие проблемы нормализации.
источник
Разработка того, что сказали другие,
Соединения - это просто декартовы произведения с некоторым блеском для губ. {1,2,3,4} X {1,2,3} даст нам 12 комбинаций (nXn = n ^ 2). Этот вычисленный набор действует как ссылка, к которой применяются условия. СУБД применяет условия (например, где левые и правые равны 2 или 3), чтобы дать нам соответствующие условия. На самом деле он более оптимизирован, но проблема та же. Изменения в размере наборов будут увеличивать размер результата в геометрической прогрессии. Количество потребляемой памяти и циклов ЦП все выражается в экспоненциальной форме.
Когда мы денормализуем, мы полностью избегаем этого вычисления, думая о том, чтобы иметь цветную наклейку, прикрепленную к каждой странице вашей книги. Вы можете вывести информацию без использования ссылки. Наказание, которое мы платим, заключается в том, что мы компрометируем сущность СУБД (оптимальная организация данных)
источник