Почему соединения плохо при рассмотрении масштабируемости?

Почему соединения плохо или 'медленные'. Я знаю, что слышал это больше затем однажды. Я нашел эту кавычку

Проблемой являются соединения, являются относительно медленными, особенно по очень большим наборам данных, и если они являются медленными, Ваш веб-сайт является медленным. Требуется много времени, чтобы получить все те отдельные биты информации от диска и поместить их всех вместе снова.

источник

Я всегда думал, что они были быстры особенно при поиске PK. Почему они являются 'медленными'?

89
задан 12 April 2010 в 17:02
поделиться

16 ответов

Масштабируемость - это предварительные вычисления, распределение или сокращение повторяющейся работы до самого необходимого, чтобы минимизировать использование ресурсов на единицу работы. Чтобы хорошо масштабироваться, вы не делаете ничего, что вам не нужно, в большом объеме, а то, что вы действительно делаете, вы делаете настолько эффективно, насколько это возможно".

В этом контексте, конечно, объединение двух отдельных источников данных происходит относительно медленно, по крайней мере, по сравнению с их отсутствием, потому что это работа, которую нужно выполнять в реальном времени в тот момент, когда пользователь запрашивает ее.

Но помните, что альтернативой является отсутствие двух отдельных частей данных вообще; вы должны поместить две разрозненные точки данных в одну запись. Вы не можете объединить два разных куска данных без каких-либо последствий, поэтому убедитесь, что вы понимаете компромисс.

Хорошая новость заключается в том, что современные реляционные базы данных хорошо справляются с объединением. Вы не должны думать о соединениях как о медленных при хорошем использовании базы данных. База данных предоставляет ряд удобных для масштабирования способов взять необработанные соединения и сделать их намного быстрее:

  • Соединение по суррогатному ключу (столбец autonumer/identity), а не по естественному ключу. Это означает меньшее (и, следовательно, более быстрое) сравнение во время операции объединения
  • Индексы
  • Материализованные/индексированные представления (рассматривайте это как предварительно вычисленное объединение или управляемую де-нормализацию)
  • Вычисленные столбцы. Вы можете использовать это для хэширования или другого предварительного вычисления ключевых столбцов соединения, так что то, что было бы сложным сравнением для соединения, теперь намного меньше и потенциально предварительно индексируется.
  • Разделы таблиц (помогает при работе с большими наборами данных, распределяя нагрузку на несколько дисков или ограничивая сканирование таблицы сканированием разделов)
  • OLAP (предварительно вычисляет результаты определенных видов запросов/соединений. Это не совсем верно, но вы можете считать это общей денормализацией)
  • Репликация, группы доступности, доставка журналов или другие механизмы, позволяющие нескольким серверам отвечать на запросы на чтение одной и той же базы данных, и таким образом масштабировать рабочую нагрузку между несколькими серверами.

Я бы даже сказал, что основная причина существования реляционных баз данных - это возможность эффективно выполнять соединения*. Конечно, это не просто хранение структурированных данных (это можно сделать с помощью плоских файлов, таких как csv или xml). Некоторые из перечисленных мною вариантов даже позволят вам полностью создать объединение заранее, так что результаты будут готовы еще до того, как вы выполните запрос - точно так же, как если бы вы денормализовали данные (правда, за счет более медленных операций записи).

Если у вас медленное объединение, вы, вероятно, неправильно используете свою базу данных.

Денормализация должна проводиться только после того, как другие методы не сработали. И единственный способ оценить "неудачу" - это установить значимые цели производительности и провести измерения в соответствии с этими целями. Если вы еще не провели измерения, то вам еще рано даже думать о де-нормализации.

* То есть, существуют как сущности, отличные от простого набора таблиц. Дополнительная причина для настоящей rdbms - безопасный параллельный доступ.

91
ответ дан 24 November 2019 в 07:16
поделиться

Соединения действительно требуют дополнительной обработки, так как они должны искать в большем количестве файлов и индексов, чтобы «соединить» данные вместе. Однако «очень большие наборы данных» относительны. Какое определение для большого? В случае JOINs, я думаю, что это ссылка на большой набор результатов, а не на общий набор данных.

Большинство баз данных могут очень быстро обработать запрос, который выбирает 5 записей из первичной таблицы и объединяет 5 записей из связанной таблицы для каждой записи (при условии наличия правильных индексов). Каждая из этих таблиц может содержать сотни миллионов записей или даже миллиарды.

Как только ваш набор результатов начнет расти, дела замедлятся. Используя тот же пример, если основная таблица дает 100 000 записей, то необходимо найти 500 000 «объединенных» записей. Просто вытащить столько данных из базы данных с дополнительными задержками.

Не избегайте JOIN, просто знайте, что вам может потребоваться оптимизация / денормализация, когда наборы данных становятся «очень большими».

3
ответ дан 24 November 2019 в 07:16
поделиться

Соединения выполняются медленно, если

  • данные неправильно проиндексированы
  • результаты плохо отфильтрованы
  • присоединение к запросу плохо написано
  • наборы данных очень большие и сложный

Итак, верно, чем больше ваши наборы данных, тем больше обработки вам потребуется для запроса, но проверка и работа над первыми тремя опциями из вышеперечисленных часто дает отличные результаты.

Ваш источник дает возможность денормализации. Это нормально, только если вы исчерпали лучшие альтернативы.

8
ответ дан 24 November 2019 в 07:16
поделиться

Хотя соединения (предположительно из-за нормализованного дизайна), очевидно, могут быть медленнее для извлечения данных, чем чтение из одной таблицы, денормализованная база данных может быть медленной для операции создания / обновления данных, поскольку объем транзакции в целом не будет минимальным.

В нормализованной базе данных фрагмент данных будет находиться только в одном месте, поэтому объем обновлений будет минимальным. В денормализованной базе данных может потребоваться обновление одного и того же столбца в нескольких строках или в разных таблицах, а это означает, что занимаемая площадь будет больше, а вероятность блокировок и взаимоблокировок может возрасти.

1
ответ дан 24 November 2019 в 07:16
поделиться

Также из статьи, которую вы процитировали:

Множество мегамасштабных веб-сайтов с миллиардами записей, петабайтами данных, множеством {{ 1}} тысячи одновременных пользователей и миллионы запросов в день используют схему сегментирования, а некоторые даже выступают за денормализацию как лучшую стратегия построения уровня данных .

и

И если вы не действительно большой веб-сайт, вам, вероятно, не нужно беспокоиться об этом уровне сложности.

и

Это больше подвержено ошибкам, чем выполнение всей этой работы базы данных , но вы можете масштабировать больше, чем могут даже базы данных самого высокого уровня. ручка.

В статье обсуждаются мегасайты вроде Ebay. На этом уровне использования вам, вероятно, придется подумать о чем-то другом, кроме простого управления реляционными базами данных. Но в «нормальном» ходе бизнеса (приложения с тысячами пользователей и миллионами записей) более дорогие и подверженные ошибкам подходы являются излишними.

3
ответ дан 24 November 2019 в 07:16
поделиться

Соединения могут быть медленными, если требуется сканировать большие части записей с каждой стороны.

Примерно так:

SELECT  SUM(transaction)
FROM    customers
JOIN    accounts
ON      account_customer = customer_id

Даже если индекс определен для account_customer , все записи из последнего все равно нужно сканировать.

Для этого списка запросов достойные оптимизаторы, вероятно, даже не будут рассматривать путь доступа к индексу, вместо этого выполняя HASH JOIN или MERGE JOIN .

Обратите внимание, что для такого запроса:

SELECT  SUM(transaction)
FROM    customers
JOIN    accounts
ON      account_customer = customer_id
WHERE   customer_last_name = 'Stellphlug'

соединение, скорее всего, будет быстрым: во-первых, индекс на customer_last_name будет использоваться для фильтрации всех Stellphlug (которые, конечно, не очень многочисленные), то сканирование индекса на account_customer будет выполнено для каждого Stellphlug, чтобы найти его транзакции.

Несмотря на то, что это могут быть миллиарды записей в учетных записях и клиентах , на самом деле нужно будет сканировать лишь некоторые из них.

7
ответ дан 24 November 2019 в 07:16
поделиться

Люди с базами данных размером в террабайт все еще используют объединения, если они могут заставить их работать с точки зрения производительности, то можете и вы.

Есть много причин не деномализировать. Во-первых, скорость выборочных запросов - не единственная и даже не главная проблема баз данных. Первостепенное значение имеет целостность данных. Если вы денормализуете, то вам нужно внедрить методы, чтобы данные оставались денормализованными по мере изменения родительских данных. Итак, предположим, что вы решили хранить имя клиента во всех таблицах вместо того, чтобы присоединяться к клиентской таблице по client_Id. Теперь, когда имя клиента изменяется (100% вероятность, что некоторые имена клиентов изменятся со временем), теперь вам нужно обновить все дочерние записи, чтобы отразить это изменение. Если вы сделаете это каскадное обновление и у вас будет миллион дочерних записей, как вы думаете, насколько быстро это будет происходить и сколько пользователей будут страдать от проблем с блокировкой и задержек в своей работе, пока это произойдет? Более того, большинство людей, которые проводят денормализацию из-за того, что «соединения выполняются медленно», не знают достаточно о базах данных, чтобы должным образом обеспечить защиту целостности их данных, и часто заканчивают тем, что базы данных содержат неиспользуемые данные из-за плохой целостности.

Денормализация - это сложный процесс, который требует глубокого понимания производительности и целостности базы данных, если она должна выполняться правильно. Не пытайтесь денормализовать, если у вас нет такого опыта в штате.

Если вы выполняете несколько действий, то соединение выполняется достаточно быстро. Сначала используйте предполагаемый ключ, соединение int почти всегда является самым быстрым соединением. Во-вторых, всегда индексируйте внешний ключ.Используйте производные таблицы или условия объединения, чтобы создать меньший набор данных для фильтрации. Если у вас большая и очень сложная база данных, наймите профессионального специалиста по базам данных с опытом разделения и управления огромными базами данных. Существует множество способов повысить производительность, не избавляясь от объединений.

Если вам просто нужна возможность запроса, то да, вы можете создать хранилище данных, которое можно денормализовать и заполнить с помощью инструмента ETL (оптимизированного для скорости), а не ввода данных пользователя.

9
ответ дан 24 November 2019 в 07:16
поделиться

Соединения могут быть медленнее, чем их избегание через де-нормализацию, но при правильном использовании (соединение по столбцам с соответствующими индексами и так далее) они не являются по своей природе медленными.

Де-нормализация - это одна из многих техник оптимизации, которую вы можете рассмотреть, если ваша хорошо спроектированная схема базы данных демонстрирует проблемы с производительностью.

30
ответ дан 24 November 2019 в 07:16
поделиться

Ну, да, выборка строк из одной денормализованной таблицы (при условии приличных индексов для вашего запроса) может быть быстрее, чем выборка строк, построенных из соединения нескольких таблиц, особенно если соединения не имеют эффективных индексов.

Примеры, приведенные в статье - Flickr и eBay - являются исключительными случаями IMO, поэтому имеют (и заслуживают) исключительные ответы. Автор специально указывает в статье на отсутствие RI и степень дублирования данных.

Большинство приложений - опять же, IMO - выигрывают от проверки и уменьшения дублирования, предоставляемых РСУБД.

1
ответ дан 24 November 2019 в 07:16
поделиться

Объем создаваемых временных данных может быть огромным на основе объединений.

Например, одна база данных здесь, на работе, имела общую функцию поиска, в которой все поля были необязательными. Процедура поиска выполняла объединение всех таблиц перед началом поиска. Вначале это сработало хорошо. Но теперь, когда в основной таблице более 10 миллионов строк ... не так много. Теперь поиск занимает 30 минут или больше.

Мне было поручено оптимизировать хранимую процедуру поиска.

Первое, что я сделал, - если производился поиск в любом из полей основной таблицы, я сделал выбор временной таблицы только для этих полей. ЗАТЕМ, я объединил все таблицы с этой временной таблицей перед тем, как продолжить поиск. Теперь поиск по одному из основных полей таблицы занимает менее 10 секунд.

Если поиск ни в одном из основных полей таблицы не начинается, я делаю аналогичные оптимизации для других таблиц. Когда я закончил, поиск не занимал больше 30 секунд, в большинстве случаев меньше 10.

Загрузка ЦП сервера SQL также СНИЗИЛАСЬ.

1
ответ дан 24 November 2019 в 07:16
поделиться

Правильно спроектированные таблицы, содержащие правильные признаки и правильно написанные запросы, не всегда медленные. Где бы вы ни слышали это:

Почему соединения плохие или «медленные»

понятия не имеют, о чем они говорят !!! Большинство присоединений будут очень быстрыми. Если вам нужно объединить много строк одновременно, вы можете получить удар по сравнению с денормализованной таблицей, но это возвращается к правильно спроектированным таблицам, знайте, когда денормализовать, а когда нет. в тяжелой системе отчетности разбейте данные в денормализованные таблицы для отчетов или даже создайте хранилище данных. В системе с тяжелыми транзакциями нормализуйте таблицы.

2
ответ дан 24 November 2019 в 07:16
поделиться

Объединения считаются силой, противоположной масштабируемости, потому что они обычно являются узким местом, и их нелегко распределить или распараллелить.

2
ответ дан 24 November 2019 в 07:16
поделиться

Соединения работают быстро. Соединения следует считать стандартной практикой при правильно нормализованной схеме базы данных. Соединения позволяют объединять разрозненные группы данных в осмысленном виде. Не бойтесь объединений.

Оговорка заключается в том, что вы должны понимать нормализацию, объединение и правильное использование индексов.

Остерегайтесь преждевременной оптимизации, поскольку главная неудача всех проектов разработки - это соблюдение сроков. После завершения проекта и понимания компромиссов можно нарушать правила, если это оправдано.

Это правда, что производительность join снижается нелинейно по мере увеличения размера набора данных. Поэтому она не так хорошо масштабируется, как запросы к одной таблице, но все же масштабируется.

Также верно, что птица летает быстрее без крыльев, но только прямо вниз.

4
ответ дан 24 November 2019 в 07:16
поделиться
В статье

говорится, что они медленные по сравнению с отсутствием объединений. это может быть достигнуто денормализацией. так что есть компромисс между скоростью и нормализацией. не забывайте также о преждевременной оптимизации :)

12
ответ дан 24 November 2019 в 07:16
поделиться

Прежде всего, смысл существования реляционной базы данных заключается в возможности моделирования отношений между сущностями. Соединения - это просто механизмы, с помощью которых мы обходим эти отношения. Они, конечно, обходятся недешево, но без джоинов реляционная база данных не имеет смысла.

В академической среде мы изучаем такие вещи, как различные нормальные формы (1-я, 2-я, 3-я, Бойса-Кодда и т.д.), узнаем о различных типах ключей (первичные, внешние, альтернативные, уникальные и т.д.) и о том, как все это сочетается при проектировании базы данных. Мы изучаем зачатки SQL, а также манипулирование структурой и данными (DDL и DML).

В корпоративном мире многие из академических конструкций оказываются гораздо менее жизнеспособными, чем мы предполагали. Прекрасным примером является понятие первичного ключа. Академически это тот атрибут (или набор атрибутов), который однозначно идентифицирует одну строку в таблице. Поэтому во многих проблемных областях правильным академическим первичным ключом является композиция из 3 или 4 атрибутов. Однако почти все в современном корпоративном мире используют в качестве первичного ключа таблицы автоматически генерируемое последовательное целое число. Почему? По двум причинам. Первая заключается в том, что это делает модель намного чище, когда вы переносите FK повсюду. Вторая, наиболее важная для данного вопроса, заключается в том, что поиск данных с помощью объединений быстрее и эффективнее для одного целого числа, чем для 4 столбцов varchar (как уже упоминалось несколькими людьми).

Теперь давайте немного углубимся в два конкретных подтипа баз данных реального мира. Первый тип - это транзакционная база данных. Это основа многих приложений электронной коммерции или управления содержимым современных сайтов. При использовании транзакционной БД вы в значительной степени оптимизируете "пропускную способность транзакций". Большинство приложений для торговли или управления контентом должны балансировать между производительностью запросов (из определенных таблиц) и производительностью вставки (в другие таблицы), хотя каждое приложение будет решать свои уникальные проблемы, обусловленные бизнесом.

Второй тип базы данных реального мира - это база данных отчетов. Они используются почти исключительно для агрегирования бизнес-данных и создания значимых бизнес-отчетов. Они, как правило, формируются иначе, чем транзакционные базы данных, в которых генерируются данные, и они сильно оптимизированы для скорости загрузки больших объемов данных (ETL) и производительности запросов с большими или сложными наборами данных.

В каждом случае разработчику или DBA необходимо тщательно сбалансировать кривые функциональности и производительности, и существует множество приемов повышения производительности с обеих сторон уравнения. В Oracle вы можете сделать так называемый "пояснительный план", чтобы увидеть, как именно будет разобран и выполнен запрос. Вы стремитесь максимизировать правильное использование индексов в БД. Одно из действительно неприятных "нет-нет" - помещать функцию в предложение where запроса. Всякий раз, когда вы это делаете, вы гарантируете, что Oracle не будет использовать индексы для этого конкретного столбца, и вы, скорее всего, увидите полное или частичное сканирование таблицы в плане объяснения. Это всего лишь один конкретный пример того, как может быть написан запрос, который в итоге окажется медленным, и он не имеет никакого отношения к джойнам.

И раз уж мы заговорили о сканировании таблицы, то очевидно, что оно влияет на скорость запроса пропорционально размеру таблицы. Полное сканирование таблицы в 100 строк даже не заметно. Выполните тот же запрос для таблицы со 100 миллионами строк, и вам придется вернуться на следующей неделе, чтобы узнать о результатах.

Давайте на минуту поговорим о нормализации. Это еще одна в значительной степени положительная академическая тема, которая может стать слишком напряженной. В большинстве случаев, когда мы говорим о нормализации, мы действительно имеем в виду устранение дубликатов данных путем помещения их в собственную таблицу и переноса FK. Люди обычно пропускают всю зависимость, описываемую 2НФ и 3НФ. И все же, в крайнем случае, можно иметь идеальную базу данных BCNF, которая огромна и является настоящим чудовищем для написания кода, потому что она настолько нормализована.

Так где же нам балансировать? Не существует единого оптимального ответа. Все лучшие ответы, как правило, являются неким компромиссом между простотой обслуживания структуры, простотой обслуживания данных и простотой создания/обслуживания кода. В целом, чем меньше дублирование данных, тем лучше.

Так почему же джойны иногда работают медленно? Иногда это плохой реляционный дизайн. Иногда это неэффективное индексирование. Иногда это проблема объема данных. Иногда это ужасно написанный запрос.

Извините за такой длинный ответ, но я чувствовал себя обязанным предоставить более полный контекст моих комментариев, а не просто разбрасываться четырьмя пулями.

12
ответ дан 24 November 2019 в 07:16
поделиться

Они могут быть медленными, если выполнены небрежно. Например, если вы выполняете «выбор *» при объединении, вам, вероятно, потребуется некоторое время, чтобы вернуть данные. Однако, если вы внимательно выберете, какие столбцы возвращать из каждой таблицы, и с соответствующими индексами, проблем возникнуть не должно.

0
ответ дан 24 November 2019 в 07:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: