Насколько дорого обходятся соединения в SQL?И / или каков компромисс между производительностью и нормализацией? - PullRequest
12 голосов
/ 25 апреля 2011

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

Я знаю, что есть обменмежду нормализацией и производительностью, и мне интересно, как лучше всего провести эту линию?В моей конкретной ситуации у меня есть система обмена сообщениями, которая имеет три различные таблицы: messages_threads (всеобъемлющий держатель сообщений), messages_recipients (кто участвует) и messages_messages (фактические сообщения + метки времени).

Для возвратав представлении «Входящие» я должен соединить таблицу messages_threads, таблицу пользователей и таблицы изображений с таблицами messages_recipients, чтобы получить информацию для заполнения представления (изображение профиля, имя отправителя, идентификатор потока) ... и яМне все еще нужно добавить объединение в сообщения для извлечения текста из последнего сообщения, чтобы отобразить «предварительный просмотр» последнего сообщения для пользователя.

Мой вопрос: насколько дорого обходятся JOINS в SQL дляспектакль?Я мог бы, например, сохранить имя отправителя (которое я должен оставить присоединенным от пользователей для извлечения) в поле в таблице messages_threads под названием «sendername» - но с точки зрения нормализации меня всегда учили избегать избыточности данных?

Где вы рисуете линию?Или я переоцениваю, насколько затрудняют соединения SQL?

Ответы [ 7 ]

21 голосов
/ 25 апреля 2011

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

Производительность составляет всего один отпроблемы, с которыми вам приходится иметь дело с базами данных.Дублируя данные, вы рискуете допустить несогласованность данных в вашей базе данных, что сводит на нет один из основных принципов реляционных баз данных, согласованность (C in ACID) a .

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

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


a) Обращение к производительности обычно можно сделать безопасным, используя триггеры для поддержания согласованности.Это, конечно, замедлит ваши обновления, но может все же позволить вашим выборам работать быстрее.

3 голосов
/ 25 апреля 2011

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

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

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

3 голосов
/ 25 апреля 2011

Я бы не стал так беспокоиться о дополнительном соединении По моему опыту, большая потеря производительности от объединений происходит, когда вы объединяете большие наборы данных. Предположительно, ваш просмотр сообщений будет отображать 20-100 рядов вершин.

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

Если вам действительно любопытно, вы можете установить тест. PHPMyAdmin говорит вам, сколько времени потребовалось для выполнения запроса; Вы можете проверить время с и без окончательного присоединения. (Помните, что все запросы на выбор в phpmyadmin ограничены, поэтому вы можете ожидать более продолжительного времени выполнения, если выбираете более 20 строк).

2 голосов
/ 25 апреля 2011

Исходя из моего опыта, влияние дополнительных сегментов JOIN в запросе, как правило, не приводит к созданию или разрушению приложения. Индексирование, избегая подзапросов и иногда избегая операторов LEFT JOIN, окажет наибольшее влияние.

Как упоминает Сэм Дюфель, установите эталонный тест, чтобы увидеть, следует ли обходить используемое вами левое соединение. Также может быть полезно сгенерировать пачку фиктивных данных, чтобы увидеть, масштабируется ли она по мере увеличения числа записей в JOIN.

1 голос
/ 25 апреля 2011

Невозможно или бесполезно ответить на вопрос о том, насколько дорогостоящие объединения.

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

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

1 голос
/ 25 апреля 2011

ВСЕГДА ВСЕГДА предпочитают нормализацию.Мне ужасно, что денормализация по-прежнему привлекает такое внимание.

NORMALIZE - это то, для чего настроены механизмы баз данных.

1 голос
/ 25 апреля 2011

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

Чего следует избегать, так это подзапросов (в первую очередь коррелированных подзапросов), которые обычно используются в качестве альтернативы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...