Как значительно оптимизировать нашу базу данных MySQL (или заменить ее) при использовании соединений?

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

sel = Ads.find(:all, :select => '*', :joins => "ПРИСОЕДИНЯЙТЕСЬ к кампаниям ПО ads.campaign_id = кампании.id ПРИСОЕДИНЯЙТЕСЬ к пользователям ПО кампаниям.user_id = users.id ВЛЕВО ПРИСОЕДИНЯЙТЕСЬ к странам ПО странам.campaign_id = кампании.id ЛЕВАЯ СОЕДИНЯЙТЕ ключевые слова ВКЛ. keywords.campaign_id = кампании.ид", :условия => [flashstr + "keywords.word = ? И ads.format = ? И кампании.cenabled = 1 И (countries.country IS NULL ИЛИ страны .country = ?) И ads.enabled = 1 И кампании.dailyenabled = 1 И users.uenabled = 1", kw, format, viewer['country'][0]], :order => order, :limit => лимит)

Мои вопросы:

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

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

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

Благодарю вас!


РЕДАКТИРОВАТЬ: вот более подробная информация:

Полностью выполненный SQL с плоским выбором (усеченный выше):

ВЫБЕРИТЕ кампании.id, кампании.guid, кампании.user_id, кампании.dailylimit, кампании.показы, кампании.cenabled, кампании.dayspent, кампании.dailyenabled, кампании.fr, ads.id, ads.guid, ads.user_id, объявления .campaign_id, ads.format, ads.enabled, ads.datafile, ads.data1, ads.data2, ads.originalfilename, ads.aid, ads.impressions, country.id, country.guid, country.campaign_id, country.country , keywords.id, keywords.campaign_id, keywords.word, keywords.bid ИЗ ads ПРИСОЕДИНЯЙТЕСЬ к кампаниям ВКЛ ads.campaign_id = кампании.ид ПРИСОЕДИНЯЙТЕСЬ к пользователям ВКЛ кампании.user_id = users.id ВЛЕВО ПРИСОЕДИНЯЙТЕСЬ к странам ВКЛ Country.campaign_id = кампании.ид ВЛЕВО ПРИСОЕДИНЯЙТЕСЬ к ключевым словам ON keywords.campaign_id = кампании.id ГДЕ (keywords.word = 'дизайн' И ads.format = 10 И кампании.cenabled = 1 И (countries.country IS NULL ИЛИ country.country = 82) И ads.enabled = 1 И кампании.dailyenabled = 1 И пользователи.uenabled = 1 И ads.datafile != '') ORDER BY keywords.bid DESC LIMIT 1,1

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

+----+-------------+-----------+--------+------------------+-------------+---------+------------------------------------+------+----------------------------------------------+
| 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)

person jkaz    schedule 14.06.2010    source источник
comment
сначала замените SELECT * только теми столбцами, которые вам нужны, и убедитесь, что у вас есть правильные индексы (посмотрите на план выполнения для сканирования)   -  person KM.    schedule 15.06.2010
comment
У меня есть, индексы есть и все, но все равно недостаточно быстро. Кроме того — KM — да, я сделал, этот код копирования / вставки был усечен до *, потому что мы захватываем много столбцов, и при вставке это выглядело бы неразборчиво. Спасибо обоим.   -  person jkaz    schedule 15.06.2010
comment
Предоставьте план выполнения, соответствующие действующие индексы и количество записей в таблицах.   -  person D'Arcy Rittich    schedule 15.06.2010
comment
Можем ли мы увидеть точное выражение SQL, которое было сгенерировано?   -  person D'Arcy Rittich    schedule 15.06.2010
comment
Ждать! ваши страны, ключевые слова, кампании и объявления меняются каждые 5 минут? черт, вы продаете рекламу, как смазанную маслом молнию. Когда IPO?   -  person Stephanie Page    schedule 15.06.2010
comment
Красный фильтр: добавлено в сообщение выше. количество записей составляет десять тысяч для всех таблиц (или меньше). Стефани: хорошая мысль, но мы просто хотели бы внести изменения как можно скорее. мы можем тянуть каждые 15 минут или даже 1 час, это просто концепция тянуть :) всем спасибо.   -  person jkaz    schedule 15.06.2010


Ответы (2)


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

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

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

Но вы можете подумать о проблеме, как предлагает Frustrated.

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

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

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

person Stephanie Page    schedule 14.06.2010
comment
Я согласен, это отличная идея, и я обязательно попробую это. Это, безусловно, будет быстрее, чем выполнение всех объединений — возможно, мы даже сможем вставить полученную плоскую базу данных в таблицу NoSQL! — так что я попробую и сообщу о результатах. Благодарю вас! - person jkaz; 15.06.2010
comment
Ммм... нет. Вы не поместите их в таблицу noSql, если вам не нужно в основном одно индексированное значение (я сказал в основном). По своей сути noSql — это просто пары ключевое слово/значение, где значение может быть сложного типа (например, адрес). Если вы хотите искать все адреса по почтовому индексу, есть дополнительные сложности, но я думаю, что последние улучшения могут ускорить это. Но это было в mySql в течение 15 лет. Индекс на зипе, вуаля. Если вы всегда используете одни и те же столбцы фильтра, ваш индекс будет очевиден, если вы смешиваете и сопоставляете, исследуйте, как mySql может использовать более одного индекса. Я писал об этом здесь. - person Stephanie Page; 15.06.2010

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

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

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

person FrustratedWithFormsDesigner    schedule 14.06.2010
comment
План выполнения выше. У меня уже были индексы, о которых вы упомянули (см. выше). Данные меняются, вероятно, примерно каждый час. Мне нравится идея вторичной таблицы, но мне кажется, что это будет очень, очень большая таблица, так как мы делаем много объединений. Может быть, лучше засунуть это в память? (кстати, у нас много памяти для работы.) Спасибо за ответ! - person jkaz; 15.06.2010
comment
@jkaz: да, я думаю, что разместил сообщение до того, как вы опубликовали информацию о плане и индексе. Выглядит хорошо, я думаю, так что пришло время оптимизировать что-то еще! Таблица/кеш в памяти с периодическими обновлениями по-прежнему лучшее, что я когда-либо видел для этого, но после кофе, возможно, у меня появятся другие идеи. ;) - person FrustratedWithFormsDesigner; 15.06.2010