Использовать MySQL для регулярного выполнения многофакторных объединений на таблицах размером более 100 ГБ

11

Справочная информация :
я создал веб-приложение, которое я хотел бы иметь возможность достаточно хорошо масштабировать. Я знаю, что я не Google или Twitter, но мое приложение использует довольно большой объем данных для каждого пользователя и, следовательно, предъявляет довольно высокие требования к данным. Я хочу быть готовым достаточно хорошо масштабироваться, не перестраивая все позже.

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

С относительно большим количеством пользователей, но не похожими на номера Facebook, я ожидаю, что у меня будет БД, которая выглядит следующим образом:

Один "Большой стол":

  • 250 миллионов записей
  • 20 столбцов
  • Примерно 100 ГБ данных
  • Имеет индексированный внешний ключ bigint (20)
  • Имеет индексированный столбец varchar (500) string_id
  • Имеет int (11) столбец «значение»

4 другие таблицы:

  • 10 миллионов записей каждая
  • Примерно 2 - 4 ГБ данных каждый
  • каждая из этих таблиц имеет 4 - 8 столбцов
  • один столбец является datetime date_created
  • один столбец является столбцом varchar (500) string_id
  • один или два столбца из каждой из этих таблиц будут выбраны в объединении

Одна из этих таблиц используется для хранения средних значений: ее схема - bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

Что я хочу сделать - два относительно дорогих запроса:

  1. Рассчитать новые средние значения:

    • Используя внешний ключ, выберите до нескольких миллионов отдельных записей из большой таблицы.
    • Вычислите новое среднее, группируя по string_id.
    • Вставьте результаты в таблицу средних значений.
    • В настоящее время этот запрос использует два соединения.
  2. Создайте ненормализованные записи только для чтения для обслуживающих пользователей:

    • Используйте внешний ключ, чтобы выбрать от 1 000 до 40 000 записей из большой таблицы.
    • Присоединитесь к каждой из четырех других таблиц в самой новой записи с помощью столбца идентификатора строки.
    • Вставьте результаты в ненормализованную таблицу.
    • Эти записи предназначены для внешнего интерфейса для отображения информации пользователям.
    • В настоящее время этот запрос использует четыре объединения.

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

Каждый из этих запросов в настоящее время выполняется в MySQL за несколько секунд на очень низкоуровневой машине с набором данных со 100K записями в «большой таблице». Я обеспокоен как своей способностью к масштабированию, так и стоимостью масштабирования.

Вопросы :

  1. Этот подход кажется правильным? Что-то явно не так с точки зрения общей картины?
  2. Является ли СУБД подходящим инструментом или я должен смотреть на другие решения для «больших данных», как что-то из семейства Hadoop? Я склонен использовать RDBMS, потому что данные структурированы и хорошо вписываются в реляционную модель. Однако в определенный момент я понимаю, что я больше не смогу использовать СУБД. Это правда? Когда будет необходим этот переключатель?
  3. Это будет работать? Могут ли эти запросы выполняться в разумные сроки? Я могу подождать, возможно, несколько часов для запроса № 1, но запрос № 2 должен завершиться через несколько минут.
  4. Что я должен рассмотреть с точки зрения аппаратного обеспечения? Какие могут быть узкие места в моей оперативной памяти и процессоре? Я предполагаю, что хранение индексов в оперативной памяти важно. Есть ли что-то еще, что я должен рассмотреть?
  5. В какой-то момент мне, вероятно, придется разделить мои данные и использовать несколько серверов. Похоже, мой вариант использования уже относится к этой категории, или я смогу какое-то время масштабировать одну машину по вертикали? Будет ли это работать с 10x данными? 100x?
xnickmx
источник
На этот вопрос сложно ответить основательно. Возможно, вам лучше исследовать характеристики производительности запросов MySQL в целом, чтобы вы знали, чего ожидать; Конечно, вы всегда можете добавить 20 дисков на сервер, чтобы вы могли читать со скоростью 3 ГБ / с или около того. Но я думаю, что вы после тщательного программного ответа.
USR

Ответы:

4

Вы пытались собрать больше данных и сравнить их? 100K строк несущественно. Попробуйте 250M или 500M, как вы ожидаете, вы должны справиться и посмотреть, где узкие места.

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

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

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

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

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

Тадман
источник
@tadman Спасибо за ваш совет. Я понимаю, что нет никакой замены для того, чтобы действительно испытать это. Я не сравнивал его с 250-миллионными строками, потому что сначала хотел убедиться, что в моем подходе нет ничего плохого. Похоже, что нет. Кроме того, собрать столько данных и сделать их более реалистичным способом - это проблема, которую я пока не понял, как ее решить. У меня есть несколько потенциальных способов разделить данные. Я думаю, что в следующий раз я просто попытаюсь увеличить свои данные и посмотреть, как это происходит на разных контрольных точках - 1M, 10M, 100M и т. Д.
xnickmx
1

Сводные таблицы.

Каждый день вычисляйте совокупную информацию для данных дня. Поместите это в «сводную» таблицу (ы). Делайте ваши запросы против них. Легко в 10 раз быстрее.

Для дальнейшего обсуждения, пожалуйста, предоставьте

  • ПОКАЗАТЬ СОЗДАТЬ СТОЛ (как оно сейчас стоит)
  • Размеры таблицы (которые вы упомянули)
  • Предлагаемые ВЫБОРЫ

Некоторые очевидные вещи ...

  • BIGINT редко гарантируется. Требуется 8 байт. INT UNSIGNED принимает 4 и допускает значения 0..4 млрд. И есть MEDIUMINT и т. Д.
  • Многочисленные индексы в таблице «фактов» обычно являются серьезной проблемой производительности, особенно для INSERT. У вас есть проблема там?
  • DATETIME составляет 8 байтов; TIMESTAMP - 4
  • Явные ИНОСТРАННЫЕ КЛЮЧЕВЫЕ ОГРАНИЧЕНИЯ хороши, но дороги
  • СОЕДИНЕНИЯ могут или не могут быть проблемой производительности; нужно увидеть SELECT и CREATEs.
  • 100 ГБ - хороший размер для «большой» базы данных MySQL; Я подозреваю, что он может работать без Hadoop и т. Д. Сейчас я имею дело с одним таким БД - большинство страниц пользовательского интерфейса реагируют менее чем за секунду, даже если данные довольно сложны.
  • Будете ли вы «очищать» данные в какой-то момент? (Это приводит к основному варианту использования для РАЗДЕЛЕНИЯ.)

"Меньше -> больше кешируется -> быстрее

Рик Джеймс
источник
0

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

Я согласен с Тэдманом. Лучше всего профилировать данные, которые вы ожидаете, в той системе, которая вам нужна.

wes.stueve
источник
Как я упоминал в своем посте, представления зависят от запроса, который использует четыре объединения таблиц с десятками миллионов записей, поэтому я не очень понимаю, как материализованное представление поможет.
xnickmx
Триггеры могут быть недостаточно быстрыми для базы данных такого размера. Сколько вставок в секунду происходит?
Рик Джеймс
1
@xnickmx Если вставок / обновлений не так много, триггеры позволяют легко / эффективно поддерживать синхронизацию денормализованных данных. Если для вставок / обновлений нужно идти быстрее, поставьте их в очередь примерно так: blog.shlomoid.com/2008/04/… или испеките свою собственную. Таким образом, вам не нужно объединяться с существующими 100 миллионами таблиц строк, чтобы получить новые данные, поскольку при срабатывании триггера вы используете тот факт, что вы знаете новые данные прямо сейчас, и можете просто денормализовать их как часть tx. или поставьте его в очередь для денормализации позже.
wes.stueve
@RickJames Согласен. Вы должны принять во внимание количество вставок для этого вида стратегии и скорость их обработки.
wes.stueve