Большие таблицы MySQL

Я работаю над проблемой, которая требует кеширования результатов "поиска" с разбивкой на страницы: Пагинация очень больших наборов данных

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

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

Теперь предположим, что я использую промежуточную таблицу MySQL в качестве своего кеша ... то есть я сохраняю первые 500 результатов для каждого элемента в таблице «совпадений», например: «item_id (INTEGER), matched_item_id (INTEGER), match_rank ( НАСТОЯЩИЙ)". Теперь поиск становится очень быстрым:

SELECT item.* FROM item, matches 
    WHERE matches.item_id=<item in question>
    AND item.id=matches.matched_item_id 
    ORDER BY match_rank DESC
    LIMIT x,y

У меня не возникнет проблем с переиндексированием элементов и их совпадений в этой таблице, поскольку они запрашиваются клиентами, если результаты старше, скажем, 24 часов. Проблема в том, что при сохранении 500 результатов для N элементов (где N составляет от ~ 100 000 до 1 000 000) эта таблица становится довольно большой ... 50 000 000 - 500 000 000 строк.

Может ли MySQL справиться с этим? На что мне следует обратить внимание?


person Sam    schedule 07.12.2008    source источник


Ответы (4)


MySQL может обрабатывать такое количество строк, и есть несколько способов масштабирования, когда вы начинаете бить о стену. Partioning и репликация являются основными решениями для этого сценария.

Вы также можете проверить дополнительные методы масштабирования для MySQL в вопросе, который я ранее задавал здесь на stackoverflow.

person Eran Galperin    schedule 07.12.2008
comment
Потрясающе .. большое спасибо. Скорее всего, я использую технику сегментирования и применяю ее к различным таблицам, базам данных, чему угодно ... это достаточно просто: сопоставьте item_id с узлом (таблица, база данных, что угодно) и запросите у этого узла результаты 500. Спасибо. - person Sam; 07.12.2008

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

Не используйте «ВЫБРАТЬ *». Больше полей означает больше операций чтения с диска.

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

Тест, тест Тест.

Если возможно, используйте таблицу только для записи (т.е. без обновлений и без удалений), чтобы mysql не повторно использовал удаленные пробелы и не заполнял индексы.

Убедитесь, что проиндексированные поля как можно короче (но не короче).

РЕДАКТИРОВАТЬ: На ум пришло еще кое-что ...

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

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

Внимательно ознакомьтесь с информацией в журнале статистики, поскольку она влияет на эффективность настроек кеша конфигурации.

Постоянно ведите «журнал медленных запросов». Это низкие накладные расходы, и это первая остановка во всех исправлениях.

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

НЕ проводите денормализацию, пока все не развалится.


Не подлежит обсуждению.

Все, что выше этой строки, - сомнительный совет. Никогда не принимайте никаких советов, не поняв их и не проверив. У каждого дизайнерского решения есть две стороны; а онлайн-советы MySQL хуже, чем обычно, делают обобщения без оговорок и без масштабирования преимуществ и штрафов. Также подвергайте сомнению все, что я здесь отметил. Поймите, что вы делаете, зачем вы это делаете и какие преимущества вы ожидаете получить. Измерьте изменения, чтобы увидеть, произошло ли то, что ожидалось.

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

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

person dkretz    schedule 07.12.2008

MySQL справится с этим. Реальный вопрос: сможет ли он справиться с этим в разумные сроки? Это зависит от вашего запроса. Как сказал Эран Гальперин в своем ответе, изучите разделение и репликацию для оптимизации.

person mepcotterell    schedule 07.12.2008

Как уже говорили другие, MySQL может легко масштабироваться для размещения очень больших наборов данных, и довольно часто он будет обрабатывать большие наборы (несколько миллионов строк) без особого вмешательства со стороны разработчика / DBA, кроме небольшого разумного индексации и оптимизации запросов. @doofledorer правильно позволяет избежать преждевременной оптимизации. Как говорят ребята из 37 Signals, если ваше приложение пользуется успехом на взлетно-посадочной полосе и у вас возникают проблемы с базой данных - что ж, это отличное место для работы.

Однако я бы ответил на этот вопрос одним из своих - действительно ли вам нужно использовать MySQL в качестве системы кеширования? Есть много мест для хранения списка из 500 int, и мой первый выбор будет на стороне сервера в сеансе. Даже если данные сеанса записываются на диск, загрузка этого массива из 500 int не будет такой медленной - и существует множество стратегий для использования кешей в памяти (таких как MemCache), чтобы еще больше ускорить это.

Цикл через массив, хранящийся в вашем сеансе, и выполнение 10, 20 (или сколько угодно на страницу) отдельных запросов по строкам «select item. * Where id = X» может показаться пугающим - это определенно приведет к увеличению физического количества запросов, но это будет молниеносно, особенно с добавлением кеширования запросов MySQL.

Изменить: Комментарии Сэма подчеркнули то, что я забыл: если вы используете, скажем, подход, основанный на сеансе, вы сразу же получите выгоду от того факта, что сеанс основан на состоянии. Вам не нужно беспокоиться об очистке просроченных данных - когда сеанс заканчивается, пуф, его больше нет. И, если вы придерживаетесь дисковых сессий (здесь я исхожу из предположения, что PHP является серверным языком), то помните, что дисковое пространство невероятно дешево.

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

person Ian    schedule 07.12.2008
comment
Мне нужно хранить до 1 000 000 списков по 500 целых. - person Sam; 07.12.2008
comment
Еще одна вещь, мое приложение определенно будет иметь безоговорочный успех. :) - person Sam; 07.12.2008
comment
Надеюсь - первый миллионер Stack Overflow? Добавлено еще несколько мыслей о подходе на основе сеансов с редактированием - person Ian; 08.12.2008