Можно ли ожидать увеличения производительности от удаления этого JOIN? - PullRequest
5 голосов
/ 08 апреля 2010

У меня есть таблица "items" с 1 миллионом строк и таблица "users" с 20 000 строк. Когда я выбираю из таблицы «items», я делаю соединение с таблицей «users» (items.user_id = user.id), чтобы я мог получить «username» из таблицы users.

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

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

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

Пример запроса с объединением:
SELECT Item. id, Item. submitter_id, Item. source_image, Item. cached_image, Item. source_title, Item. source_url, Item. width, Item. height, Item. status, Item. popular, Item. made_popular, Item. fave_count, Item . tags, Item. user_art, Item. nudity, Item. created, Item. modified, Item. removed, Item. nofront, Item. test, Item. recs, Item. recs_data, User. id, User. username, User. password , User. email, User. fullname, User. profileurl, User. homepage, User. bio, User. location, User. avatar, User. ff_user, User. ff_key, User. ff_last_faveid, User. twitter_user, User. twitter_pass, User . emailalerts, User. showunsafe, User. view, User. fb_uid, User. fb_session, User. fb_avatar, User. twitter_uid, User. twitter_data, User. twitter_autopost, User. uri, User. created, User. modified ОТ items AS Item СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ users КАК User ВКЛ (Item. submitter_id = User. id) ГДЕ Item. nofront! = 1 И Item. removed! = 1 И Item. made_popular - не NULL И ОБНАЖЕНИЕ! = 1 ЗАКАЗАТЬ Item. made_popular DESC LIMIT 1040, 290;

Пример запроса без объединения:
SELECT Item. id, Item. submitter_id, Item. source_image, Item. cached_image, Item. source_title, Item. source_url, Item. width, Item. height, Item. status, Item. popular, Item. made_popular, Item. fave_count, Item . tags, Item. user_art, Item. nudity, Item. created, Item. modified, Item. removed, Item. nofront, Item. test, Item. recs, Item. recs_data ОТ items КАК Item ГДЕ Item. nofront! = 1 И Item. removed! = 1 И Item. made_popular не равно NULL И ОБНАРУЖЕНИЮ! = 1 ЗАКАЗАТЬ ПО Item. made_popular DESC LIMIT 1040, 290;

Ответы [ 5 ]

5 голосов
/ 08 апреля 2010

Правильный ответ состоит в том, чтобы измерить его, в целевой среде , чтобы увидеть, имеет ли это значение.Затем выполните анализ затрат и выгод, чтобы выяснить, стоит ли оно того.

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

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

В любом случае дублирование столбца можно легко контролировать в приличной СУБД с помощью триггеров.Под этим я подразумеваю поместить триггер вставки / обновления в таблицу пользователей, чтобы, если пользователь меняет свое имя пользователя, он также изменялся в таблице элементов (и, возможно, наоборот).

Соответствует ли MySQL моемуопределение достойной СУБД, я не могу комментировать - я сам являюсь DB2.Но возврат из третьей нормальной формы - это проверенный и проверенный метод для извлечения каждой последней унции производительности из баз данных, и, если вы понимаете последствия, вполне приемлемо.Мало кто жалуется на то, что их базы данных занимают слишком много места на диске. Многие жалуются на то, как медленно выполняются их запросы.

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


На основена ваши добавленные запросы у меня есть пара замечаний:

  • Во-первых, столбец nudity.Скажите, пожалуйста, как мне получить доступ к этой базе данных: -)
  • Вы должны только извлечь нужные вам столбцы.Если имя пользователя - это все, что вам нужно из таблицы User, вы не должны получать все эти дополнительные данные в первом запросе.Возможно также и для материала Item - получайте только то, что вам нужно.
  • Убедитесь, что у вас есть индексы для всех столбцов, используемых в предложениях WHERE - это может также повлечь за собой комбинированные индексы (с несколькими столбцами),То, что индексируется, зависит от ваших запросов, но каждый столбец, используемый в предложениях WHERE, является хорошим началом для анализа.
  • Для больших таблиц вы можете периодически рассматривать "удаление" удаленных элементов в отдельную таблицу (например,RemovedItems), чтобы минимизировать размер Items и ускорить запросы.Но имейте в виду, что это полезно только в том случае, если вам редко нужно искать ромодированные элементы, так как это усложнит эти запросы (заставляя их искать в двух таблицах вместо одной).Опять же, это вещь цена / выгода.Один миллион строк - это не такая большая таблица (по крайней мере, в моем мире).
1 голос
/ 08 апреля 2010

Я предлагаю вам сохранить его таким образом, чтобы сохранить нормализованную таблицу.Я думаю, что не стоит помещать имена пользователей в таблицу элементов, поскольку это сделает данные избыточными.Вы пробовали переиндексировать свою таблицу?

0 голосов
/ 08 апреля 2010

У меня есть таблица "items" с 1 миллионом строк и таблица "users" с 20000 строк.

То есть, независимо от того, JOIN вы или денормализованы, вы все равно передаете примерно 1M / 20k = в 50 раз больше User информации по проводам, чем это строго необходимо. Кодирование, передача и затем декодирование данных добавляет нагрузку.

Я рассматриваю возможность добавления столбца имени пользователя в таблицу элементов и удаления объединения.

Почему вы, в своем оригинальном JOIN, также переносите всю эту другую (потенциально объемную) информацию (такую ​​как User.profileurl, User.homepage и т. Д.), Если все, что вам нужно, - это имя пользователя? Помните, что для User столбцов вы передаете в среднем 50 копий каждого бита информации. Рассматривали ли вы радикальное сокращение колонок, из которых вы SELECT берете в JOIN (как из User, так и из Item таблиц?)

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

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

На втором этапе позвольте мне начать с моего собственного вопроса: вам действительно нужны все миллионы строк за один снимок? Если нет, например, если вы работаете с пользовательским интерфейсом и разбиваете на страницы (используя OFFSET ... LIMIT ...), то вам не обязательно беспокоиться о дублировании информации 50x User (если только LIMIT не попадет в десятки тысяч). В противном случае вы можете хотите измерить преимущество , исключающее 50-кратное дублирование при первом SELECT ing только User.id и User.username в памяти приложения (20 тыс. пар в хеш-таблицу / карту), затем SELECT ing only Item строк (1M итераций) при каждом разрешении на уровне приложения Item.user_id против хеш-таблицы / карты.

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

0 голосов
/ 08 апреля 2010

JOINS всегда занимают больше ресурсов, чем простые операторы SELECT. Так что да, удаление JOIN должно повысить производительность.

0 голосов
/ 08 апреля 2010

Значительное увеличение производительности вы увидите только в том случае, если у вас отсутствует индекс по items.user_id или user.id или если вы используете дрянную базу данных. В противном случае производительность не улучшится значительно.

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