Масштабируемость - это все о предварительных вычислениях (кэшировании), распределении или разделении повторяющейся работы до самого необходимого, чтобы минимизировать использование ресурсов на единицу работы. Чтобы хорошо масштабироваться, вы не делаете то, что вам не нужно в объеме, а то, что вы действительно делаете, вы делаете максимально эффективно.
В этом контексте, конечно, объединение двух отдельных источников данных происходит относительно медленно, по крайней мере, по сравнению с тем, чтобы не объединять их, потому что это работа, которую вам нужно выполнять в реальном времени в точке, где пользователь запрашивает ее.
Но помните, что альтернатива больше не имеет двух отдельных частей данных; вы должны поместить две разные точки данных в одну запись. Вы не можете объединить два разных фрагмента данных без каких-либо последствий, поэтому убедитесь, что вы понимаете компромисс.
Хорошая новость в том, что современные реляционные базы данных хорошо справляются с объединениями. Вам не следует думать о соединениях как о медленных, если хорошо используется хорошая база данных. Есть несколько удобных для масштабирования способов сделать необработанные соединения и сделать их намного быстрее:
- Присоединитесь по суррогатному ключу (столбец autonumer / identity), а не по естественному ключу. Это означает меньшие (и, следовательно, более быстрые) сравнения во время операции соединения.
- Индексы
- Материализованные / индексированные представления (воспринимайте это как предварительно вычисленное соединение или управляемую денормализацию)
- Вычисляемые столбцы. Вы можете использовать это для хеширования или иным образом предварительно вычислить ключевые столбцы соединения, так что то, что было бы сложным сравнением для соединения, теперь намного меньше и потенциально предварительно индексируется.
- Разделы таблицы (помогает с большими наборами данных, распределяя нагрузку на несколько дисков или ограничивая то, что могло быть сканированием таблицы, вплоть до сканирования раздела)
- OLAP (предварительно вычисляет результаты определенных типов запросов / объединений. Это не совсем так, но вы можете думать об этом как об общей денормализации)
- Репликация, группы доступности, доставка журналов или другие механизмы, позволяющие нескольким серверам отвечать на запросы чтения для одной и той же базы данных и, таким образом, масштабировать вашу рабочую нагрузку между несколькими серверами.
- Использование уровня кэширования, такого как Redis, чтобы избежать повторного выполнения запросов, требующих сложных соединений.
Я бы сказал, что основная причина, по которой реляционные базы данных вообще существуют, - это возможность эффективно выполнять соединения * . Это, конечно, не только для хранения структурированных данных (вы можете сделать это с помощью таких конструкций плоских файлов, как csv или xml). Некоторые из перечисленных мною опций даже позволят вам заранее полностью построить ваше соединение, поэтому результаты уже получены до того, как вы отправите запрос - так же, как если бы вы денормализовали данные (по общему признанию, за счет более медленных операций записи).
Если у вас медленное соединение, вы, вероятно, неправильно используете свою базу данных.
Денормализацию следует проводить только после того, как эти другие методы не сработали. И единственный способ по-настоящему судить о «неудаче» - это установить значимые цели производительности и измерить их. Если вы не измеряли, то еще рано даже думать о денормализации.
* То есть существуют как объекты, отличные от простых наборов таблиц. Дополнительная причина для настоящего rdbms - безопасный одновременный доступ.
Соединения могут быть медленнее, чем их избегание посредством денормализации, но при правильном использовании (соединение по столбцам с соответствующими индексами и т. Д.) Они по своей сути не медленные .
Денормализация - это один из многих методов оптимизации, которые вы можете рассмотреть, если хорошо спроектированная схема базы данных имеет проблемы с производительностью.
источник
в статье говорится, что они медленные по сравнению с отсутствием соединений. это может быть достигнуто денормализацией. так что есть компромисс между скоростью и нормализацией. не забывайте и о преждевременной оптимизации :)
источник
Во-первых, смысл существования (причина существования) реляционной базы данных - это возможность моделировать отношения между сущностями. Объединения - это просто механизмы, с помощью которых мы проходим эти отношения. Они, безусловно, имеют номинальную стоимость, но без объединений нет смысла иметь реляционную базу данных.
В академическом мире мы узнаем о таких вещах, как различные нормальные формы (1-я, 2-я, 3-я, Бойса-Кодда и т. Д.), И мы узнаем о различных типах ключей (первичный, внешний, альтернативный, уникальный и т. Д.) И о том, как эти вещи подходят друг другу для создания базы данных. И мы изучаем основы SQL, а также манипулируем структурой и данными (DDL и DML).
В корпоративном мире многие академические конструкции оказываются существенно менее жизнеспособными, чем нас заставляли думать. Прекрасный пример - понятие первичного ключа. С академической точки зрения это тот атрибут (или набор атрибутов), который однозначно определяет одну строку в таблице. Таким образом, во многих проблемных областях правильный академический первичный ключ состоит из 3 или 4 атрибутов. Однако почти все в современном корпоративном мире используют автоматически сгенерированное последовательное целое число в качестве первичного ключа таблицы. Зачем? Две причины. Во-первых, это делает модель намного чище, когда вы переносите FK повсюду. Второй и наиболее уместный для этого вопроса заключается в том, что получение данных с помощью объединений выполняется быстрее и эффективнее для одного целого числа, чем для 4 столбцов varchar (как уже упоминалось некоторыми людьми).
Давайте теперь углубимся в два конкретных подтипа реальных баз данных. Первый тип - это транзакционная база данных. Это основа для многих приложений электронной коммерции или управления контентом, управляющих современными сайтами. С транзакционной БД вы сильно оптимизируете «пропускную способность транзакций». Большинство приложений для торговли или контента должны сбалансировать производительность запросов (из определенных таблиц) с производительностью вставки (в других таблицах), хотя каждое приложение будет решать свои собственные уникальные бизнес-задачи.
Второй тип реальных баз данных - это база данных отчетов. Они используются почти исключительно для агрегирования бизнес-данных и создания содержательных бизнес-отчетов. Как правило, они имеют форму, отличную от формы баз данных транзакций, в которых генерируются данные, и в значительной степени оптимизированы для скорости массовой загрузки данных (ETL) и производительности запросов с большими или сложными наборами данных.
В каждом случае разработчик или администратор баз данных должен тщательно сбалансировать кривые функциональности и производительности, и есть множество приемов повышения производительности с обеих сторон уравнения. В Oracle вы можете делать то, что называется «планом объяснения», чтобы вы могли конкретно видеть, как запрос анализируется и выполняется. Вы хотите максимально использовать индексы в БД. Одно действительно неприятное запрещение - это поместить функцию в предложение where запроса. Каждый раз, когда вы это делаете, вы гарантируете, что Oracle не будет использовать какие-либо индексы в этом конкретном столбце, и вы, вероятно, увидите полное или частичное сканирование таблицы в плане объяснения. Это всего лишь один конкретный пример того, как можно написать запрос, который в конечном итоге оказывается медленным и не имеет ничего общего с соединениями.
И хотя мы говорим о сканировании таблиц, очевидно, что они влияют на скорость запроса пропорционально размеру таблицы. Полное сканирование таблицы из 100 строк даже не заметно. Запустите тот же запрос к таблице со 100 миллионами строк, и вам нужно будет вернуться на следующей неделе, чтобы получить результат.
Поговорим о нормализации минутку. Это еще одна в значительной степени положительная академическая тема, которую можно переоценить. В большинстве случаев, когда мы говорим о нормализации, мы действительно имеем в виду устранение повторяющихся данных путем помещения их в отдельную таблицу и переноса FK. Люди обычно пропускают всю зависимость, описываемую 2NF и 3NF. И все же в крайнем случае, безусловно, возможно иметь совершенную базу данных BCNF, которая огромна и полная зверюга для написания кода, потому что она настолько нормализована.
Итак, где нам балансировать? Нет лучшего ответа. Все лучшие ответы, как правило, представляют собой некоторый компромисс между простотой обслуживания структуры, простотой обслуживания данных и простотой создания / обслуживания кода. В общем, чем меньше дублирование данных, тем лучше.
Так почему же соединения иногда бывают медленными? Иногда это плохой реляционный дизайн. Иногда это неэффективная индексация. Иногда это проблема с объемом данных. Иногда это ужасно написанный запрос.
Приносим извинения за такой многословный ответ, но я чувствовал себя обязанным предоставить более содержательный контекст моих комментариев, а не просто болтать ответ из четырех пунктов.
источник
Люди с базами данных размером в террабайт все еще используют объединения, если они могут заставить их работать с точки зрения производительности, то можете и вы.
Есть много причин не деномализировать. Во-первых, скорость выборочных запросов - не единственная и даже не главная проблема баз данных. Первоочередная задача - целостность данных. Если вы денормализуете, тогда вам нужно применить методы, чтобы данные оставались денормализованными по мере изменения родительских данных. Итак, предположим, что вы собираетесь хранить имя клиента во всех таблицах вместо присоединения к клиентской таблице по client_Id. Теперь, когда имя клиента изменяется (100% вероятность, что некоторые имена клиентов со временем изменятся), теперь вам нужно обновить все дочерние записи, чтобы отразить это изменение. Если вы сделаете это с каскадным обновлением и у вас будет миллион дочерних записей, как вы думаете, насколько быстро это будет происходить и сколько пользователей будут страдать от проблем с блокировкой и задержек в своей работе, пока это произойдет? Кроме того, большинство людей, которые денормализируют, потому что "
Денормализация - это сложный процесс, который требует глубокого понимания производительности и целостности базы данных, если он должен выполняться правильно. Не пытайтесь денормализовать, если у вас нет такого опыта в штате.
Присоединение происходит достаточно быстро, если вы делаете несколько вещей. Сначала используйте предполагаемый ключ, соединение int почти всегда является самым быстрым соединением. Второй всегда индексирует внешний ключ. Используйте производные таблицы или условия объединения, чтобы создать меньший набор данных для фильтрации. Если у вас большая и очень сложная база данных, наймите профессионального специалиста по базам данных с опытом разделения и управления огромными базами данных. Существует множество способов повысить производительность, не избавляясь от объединений.
Если вам просто нужна возможность запросов, то да, вы можете создать хранилище данных, которое можно денормализовать и заполнить с помощью инструмента ETL (оптимизированного для скорости), а не ввода данных пользователя.
источник
Присоединение происходит медленно, если
Итак, правда, чем больше ваши наборы данных, тем больше обработки вам потребуется для запроса, но проверка и работа над первыми тремя опциями из вышеперечисленного часто дает отличные результаты.
Ваш источник дает возможность денормализации. Это нормально, только если вы исчерпали лучшие альтернативы.
источник
Соединения могут быть медленными, если необходимо сканировать большие части записей с каждой стороны.
Как это:
SELECT SUM(transaction) FROM customers JOIN accounts ON account_customer = customer_id
Даже если индекс задан
account_customer
, все записи из последнего все равно нужно просканировать.Для этого списка запросов достойные оптимизаторы, вероятно, даже не будут рассматривать путь доступа к индексу, вместо этого выполняя a
HASH JOIN
или aMERGE JOIN
.Обратите внимание, что для такого запроса:
SELECT SUM(transaction) FROM customers JOIN accounts ON account_customer = customer_id WHERE customer_last_name = 'Stellphlug'
соединение, скорее всего, будет быстрым: сначала
customer_last_name
будет использоваться индекс on для фильтрации всех Stellphlug (которых, конечно, не очень много), затем будет выполнено сканирование индексаaccount_customer
для каждого Stellphlug, чтобы найти его транзакции.Несмотря на то, что это могут быть миллиарды записей
accounts
иcustomers
лишь немногие из них действительно нужно будет сканировать.источник
accounts(account_customer)
большинстве СУБД, он будет использовать этот индекс, чтобы точно определить, какие строкиcustomers
базы данных необходимо сканировать.HASH JOIN
будет намного быстрее, поэтому он будет использоваться, за исключением всех основных баз данных, за исключением тогоMySQL
, что будет просто делатьcustomers
ведущие во вложенном цикле (поскольку он меньше по размеру)Joins are fast.
Соединения следует рассматривать как стандартную практику с правильно нормализованной схемой базы данных. Объединения позволяют объединять разрозненные группы данных осмысленным образом. Не бойтесь соединения.Предостережение: вы должны понимать нормализацию, объединение и правильное использование индексов.
Остерегайтесь преждевременной оптимизации, так как главный провал всех проектов разработки - это соблюдение сроков. После того, как вы завершите проект и поймете возможные компромиссы, вы можете нарушить правила, если сможете это оправдать.
Это правда, что производительность соединения нелинейно ухудшается по мере увеличения размера набора данных. Следовательно, он не так хорошо масштабируется, как запросы к отдельной таблице, но все же масштабируется.
Верно и то, что птица летит быстрее без крыльев, но только прямо вниз.
источник
Соединения действительно требуют дополнительной обработки, поскольку им нужно искать в большем количестве файлов и индексов, чтобы «соединить» данные вместе. Однако «очень большие наборы данных» относительны. Какое определение для большого? В случае JOINs, я думаю, что это ссылка на большой набор результатов, а не на общий набор данных.
Большинство баз данных могут очень быстро обработать запрос, который выбирает 5 записей из первичной таблицы и объединяет 5 записей из связанной таблицы для каждой записи (при условии наличия правильных индексов). Каждая из этих таблиц может содержать сотни миллионов записей или даже миллиарды.
Как только ваш набор результатов начнет расти, все замедлится. Используя тот же пример, если основная таблица дает 100 000 записей, то необходимо найти 500 000 «объединенных» записей. Просто вытащить столько данных из базы данных с дополнительными задержками.
Не избегайте JOIN, просто знайте, что вам может потребоваться оптимизация / денормализация, когда наборы данных становятся «очень большими».
источник
Также из цитированной вами статьи:
а также
а также
В статье обсуждаются мегасайты вроде Ebay. На этом уровне использования вам, вероятно, придется подумать о чем-то другом, кроме простого управления реляционными базами данных. Но в «нормальном» ходе бизнеса (приложения с тысячами пользователей и миллионами записей) более дорогие и более подверженные ошибкам подходы являются излишними.
источник
Объединения считаются силой, противоположной масштабируемости, потому что обычно они являются узким местом, и их нелегко распределить или распараллелить.
источник
Правильно оформленные таблицы, содержащие правильные признаки и правильно написанные запросы, не всегда работают медленно. Где бы вы это ни слышали:
понятия не имеет, о чем они говорят !!! Большинство присоединений будут очень быстрыми. Если вам нужно объединить множество строк одновременно, вы можете получить удар по сравнению с денормализованной таблицей, но это возвращается к правильно спроектированным таблицам, знайте, когда денормализовать, а когда нет. в тяжелой системе отчетности разбейте данные в денормализованные таблицы для отчетов или даже создайте хранилище данных. В системе с тяжелыми транзакциями нормализуйте таблицы.
источник
Количество генерируемых временных данных может быть огромным из-за объединений.
Например, в одной из баз данных здесь, на работе, была общая функция поиска, в которой все поля были необязательными. Процедура поиска выполняла объединение всех таблиц перед началом поиска. Вначале это сработало хорошо. Но теперь, когда в основной таблице более 10 миллионов строк ... не так много. Теперь поиск занимает 30 минут или больше.
Мне было поручено оптимизировать хранимую процедуру поиска.
Первое, что я сделал, - если в каком-либо из полей основной таблицы производился поиск, я выбрал временную таблицу только для этих полей. ЗАТЕМ, я объединил все таблицы с этой временной таблицей перед тем, как продолжить поиск. Поиск по одному из основных полей таблицы теперь занимает менее 10 секунд.
Если поиск ни в одном из основных полей таблицы не начинается, я делаю аналогичные оптимизации для других таблиц. Когда я закончил, поиск не занимал больше 30 секунд, в большинстве случаев меньше 10.
Загрузка ЦП сервера SQL также СНИЗИЛАСЬ.
источник
В то время как соединения (предположительно из-за нормализованного дизайна), очевидно, могут быть медленнее для извлечения данных, чем чтение из одной таблицы, денормализованная база данных может быть медленной для операций создания / обновления данных, поскольку объем всей транзакции не будет минимальным.
В нормализованной базе данных часть данных будет находиться только в одном месте, поэтому объем обновлений будет минимальным. В денормализованной базе данных может потребоваться обновление одного и того же столбца в нескольких строках или в разных таблицах, что означает, что занимаемая площадь будет больше, а вероятность блокировок и взаимоблокировок может возрасти.
источник
Что ж, да, выбор строк из одной денормализованной таблицы (при условии наличия подходящих индексов для вашего запроса) может быть быстрее, чем выбор строк, созданных путем объединения нескольких таблиц, особенно если у объединений нет доступных эффективных индексов.
Примеры, приведенные в статье - Flickr и eBay - являются исключительными случаями, ИМО, поэтому имеют (и заслуживают) исключительные ответы. Автор особо отмечает отсутствие RI и степень дублирования данных в статье.
Большинство приложений - опять же, IMO - выигрывают от проверки и уменьшения дублирования, обеспечиваемых СУБД.
источник
Они могут быть медленными, если их делать небрежно. Например, если вы выполняете «выбор *» при объединении, вам, вероятно, потребуется некоторое время, чтобы вернуть данные. Однако, если вы внимательно выберете, какие столбцы возвращать из каждой таблицы, и с соответствующими индексами, проблем возникнуть не должно.
источник