Как мы можем значительно оптимизировать нашу базу данных MySQL (или заменить ее) при использовании объединений? - PullRequest
1 голос
/ 15 июня 2010

Это первый раз, когда я подхожу к ситуации с чрезвычайно большим объемом. Это рекламный сервер на базе MySQL. Тем не менее, используемый запрос включает в себя множество JOIN и обычно просто slow . (Это Rails ActiveRecord, кстати)

sel = Ads.find (: all,: select => '*',: joins => "ПРИСОЕДИНЯЙТЕСЬ к кампаниям на ads.campaign_id = campaigns.id ПРИСОЕДИНЯЙТЕСЬ к пользователям в кампании. .campaign_id = campaigns.id СЛЕДУЕТ ПОДКЛЮЧИТЬ КЛЮЧЕВЫЕ КЛЮЧЕВЫЕ НА КЛЮЧЕВЫЕ КЛИНЫ .campaign_id = campaigns.id ",: условие => [flashstr +" ключевые слова. NULL ИЛИ country.country =?) AND ads.enabled = 1 AND campaigns.dailyenabled = 1 AND users.uenabled = 1 ", квт, формат, просмотрщик ['country'] [0]],: order => order,: предел => предел)

Мои вопросы:

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

  2. Иначе, запустил бы экземпляр MySQL, загрузил бы локальную базу данных в память и перезагрузил бы, что каждые 5 минут помогает?

  3. В противном случае, могу ли я как-то переключить всю эту операцию на Redis или Cassandra и каким-то образом изменить поведение JOIN, чтобы оно соответствовало (не-JOIN-совместимой) природе NoSQL?

Спасибо!


РЕДАКТИРОВАТЬ: здесь более подробно:

Полный исполняемый SQL с уплощенным выбором (усечено выше):

SELECT campaigns.id, campaigns.guid, campaigns.user_id, campaigns.dailylimit, campaigns.impressions, campaigns.cenabled, campaigns.dayspent, campaigns.dailyenabled, campaigns.fr, ads.id, ads.guid, ads. user_id, ads.campaign_id, ads.format, ads.enabled, ads.datafile, ads.data1, ads.data2, ads.originalfilename, ads.aid, ads.impressions, country.id, country.guid, states.campaign_id, country.country, Keywords.id ,words.campaign_id ,words.word ,words.bid ОТ ads ПРИСОЕДИНЯТЬ Кампании НА ads.campaign_id = campaigns.id ПРИСОЕДИНЯЙТЕСЬ к пользователям НА кампаниюs.s. = campaigns.id СЛЕДУЕТ ПОДКЛЮЧИТЬ КЛЮЧЕВЫМ КЛЮЧЕВЫМ НА КЛЮЧЕВЫЕ КЛЮЧЕ. AND ads.enabled = 1 AND campaigns.dailyenabled = 1 AND users.uenabled = 1 AND ads.datafile! = '') ЗАКАЗАТЬ по ключевым словам.

ОБЪЯСНИТЬ / план выполнения:

+----+-------------+-----------+--------+------------------+-------------+---------+------------------------------------+------+----------------------------------------------+
| id | select_type | table     | type   | possible_keys    | key         | key_len | ref                                | rows | Extra                                        |
+----+-------------+-----------+--------+------------------+-------------+---------+------------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | keywords  | ref    | campaign_id,word | word        | 257     | const                              |    9 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | ads       | ref    | campaign_id      | campaign_id | 4       | e_development.keywords.campaign_id |    8 | Using where                                  | 
|  1 | SIMPLE      | campaigns | eq_ref | PRIMARY          | PRIMARY     | 4       | e_development.keywords.campaign_id |    1 | Using where                                  | 
|  1 | SIMPLE      | users     | eq_ref | PRIMARY          | PRIMARY     | 4       | e_development.campaigns.user_id    |    1 | Using where                                  | 
|  1 | SIMPLE      | countries | ALL    | campaign_id      | NULL        | NULL    | NULL                               |    4 | Using where                                  | 
+----+-------------+-----------+--------+------------------+-------------+---------+------------------------------------+------+----------------------------------------------+

(это находится в базе данных разработки, в которой не так много строк, как в рабочей версии.)

ОПРЕДЕЛЕННЫЕ ИНДЕКСЫ:

ads -> id (primary, autoinc) + aid (unique) + campaign_id (index) + user_id (index)
campaigns -> id (primary, autoinc) + user_id (index)
countries -> id (primary, autoinc) + campaign_id (index) + country (index) + user_id (index)
keywords -> id (primary, autoinc) + campaign_id (index) + word (index) + user_id (index)
user -> id (primary, autoinc)

Ответы [ 2 ]

3 голосов
/ 15 июня 2010

Теория базы данных и номинальная практика существуют, чтобы обеспечить основу для большинства случаев. Не каждый шаблон использования базы данных аккуратно вписывается в третью нормальную форму. Отсюда и появление NoSQL. Эти базы данных не работают хорошо в большинстве случаев, но отлично работают в определенных случаях. Одна из причин, по которой они работают хорошо, заключается в том, что они НЕ работают как обычные РСУБД. У Кассандры действительно есть возможность «присоединиться», но я не помню точных деталей. Если вы хотите быстрого понимания, я бы порекомендовал блог разработчиков Digg. Есть хорошее простое описание.

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

Попытка решить проблему ТОЧНО ЖЕ, то, что ТОЧНО ЖЕ с помощью другого движка, не поможет: вам нужно ДУМАТЬ как разработчик NoSQL, а не разработчик СУБД, использующий NoSQL.

Но вы можете думать о проблеме так, как предлагает Фрустрированный.

Почему у нас третья нормальная форма? Простота обновления в основном. Я обновляю одну строку вместо десятков. Это также помогает ограничить данные, если я тщательно контролирую добавление стран в таблицу стран, я никогда не получу плохую в таблице кампании. После этого 3NF не делает запросы быстрее, поэтому мы изобрели базы данных отчетов, OLAP, Cubes, Star Schemas.

Ключ в том, что это другая структура для отчетности и редактирования / захвата.

Как сказал Фрустрированный, определите скорость изменения ваших базовых данных. Если вы действительно добавляете страны каждые 5 минут, я буду ошеломлен. Кампания? вероятно случайный? Объявления? пару раз в день. Сколько времени потребуется, чтобы построить полностью сплющенную таблицу и проиндексировать ее? Сколько строк это производит? если это время цикла намного меньше вашей частоты обновления ... создайте его и посмотрите. Проверьте скорость запроса. Это более дешевый эксперимент, чем переход на совершенно новую БД.

1 голос
/ 15 июня 2010

Вы проанализировали свой план выполнения? Вы проанализировали свои показатели?

Моим первым предположением будет то, что вам нужен индекс на campaigns для user_id, индекс на countries для campaign_id, на keywords на campaign_id ... возможно, другие. Вам нужно получить план выполнения, чтобы увидеть, что делает ваш запрос.

Другой вариант: как часто изменяются данные в этом наборе результатов? К минуте? Час? День? Если это ежедневно или ежечасно (ну, несколько часов), может быть лучше иметь вторичную таблицу, которая содержит ВСЕ столбцы (или только столбцы, которые вряд ли будут часто меняться) этого набора результатов и заполняется этим запросом каждые n часов. Тогда ваше приложение просто запросит дополнительную таблицу (или, возможно, объединит одну таблицу с часто меняющимися данными), в этом случае она может быть быстрее.

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