Використовувати MySQL для регулярного приєднання багатосторонніх таблиць на 100+ ГБ?


11

Передумови :
я створив веб-додаток, який хотів би мати можливість досить масштабувати. Я знаю, що я не Google або Twitter, але мій додаток використовує досить великий об'єм даних для кожного користувача і, таким чином, має досить високі вимоги до даних. Я хочу бути готовим до масштабування досить добре, не пізніше переробляти все пізніше.

Я вважаю себе розробником програмного забезпечення, а не експертом по базі даних. Тому я розміщую тут. Сподіваюся, хтось із значно більшим досвідом роботи з базами даних може дати мені поради.

Маючи відносно велику кількість користувачів, але нічого подібного до номерів у Facebook, я очікую, що у вас є БД, який виглядає так:

Один "Великий стіл":

  • 250 мільйонів записів
  • 20 стовпців
  • Приблизно 100 ГБ даних
  • Має індексований іноземний ключ bigint (20)
  • Має індексовану колонку varchar (500) string_id
  • Має стовпець "значення" int (11)

4 інші таблиці:

  • По 10 мільйонів записів кожен
  • Приблизно 2 - 4 ГБ даних кожен
  • кожна з цих таблиць має 4 - 8 стовпців
  • один стовпчик - дата-дата_створене
  • один стовпець - це колонка varchar (500) string_id
  • один або два стовпчики з кожної з цих таблиць будуть вибрані в об'єднанні

Одна з цих таблиць використовується для зберігання середніх значень - її схема - bigint (20) id, varchar (20) string_id, datetime date_create, float prose_value

Що я хочу зробити - два відносно дорогі запити:

  1. Обчисліть нові середні значення:

    • За допомогою іноземного ключа виберіть до великої таблиці до декількох мільйонів окремих записів.
    • Обчисліть нове середнє, групуючи по string_id.
    • Вставте результати в таблицю середніх значень.
    • Як створено в даний час, цей запит використовує два об'єднання.
  2. Створюйте денормовані записи, які доступні лише для читання для обслуговування користувачів:

    • Використовуйте іноземний ключ, щоб вибрати з великого столу десь 1000-1000 записів.
    • Об’єднайтеся з кожною з інших чотирьох таблиць у найновішому записі за допомогою стовпця "id".
    • Вставте результати в денормалізовану таблицю.
    • Ці записи призначені для використання в передній частині для відображення інформації для користувачів.
    • Як створено в даний час, цей запит використовує чотири приєднання.

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

Кожен з цих запитів в даний час виконується за кілька секунд у MySQL на дуже низькій версії машини із набором даних із 100 К-записами у "великій таблиці". Мене хвилює як моя здатність до масштабування, так і витрати на масштабування.

Запитання :

  1. Чи здається цей підхід здоровим? Чи є щось очевидно з цим з точки зору великої картини?
  2. Чи RDBMS - це правильний інструмент, чи я повинен дивитись на інші рішення "великих даних", як на щось із сімейства Hadoop? Моя схильність - використовувати RDBMS, оскільки дані структуровані і добре вписуються у реляційну модель. Але в певний момент я розумію, що я більше не можу використовувати RDBMS. Це правда? Коли цей комутатор знадобиться?
  3. Чи буде це працювати? Чи можуть ці запити виконуватись у розумний проміжок часу? Я можу зачекати, можливо, години на запит №1, але запит №2 повинен закінчитися за лічені хвилини.
  4. Що я повинен розглянути з точки зору обладнання? Якими можуть бути вузькі місця оперативної пам’яті та процесора? Я вважаю, що важливо зберігати індекси в оперативній пам'яті. Чи є ще щось, що я повинен розглянути?
  5. В якийсь момент мені, мабуть, доведеться розділити свої дані та використовувати декілька серверів. Чи здається, що мій випадок використання вже є в цій категорії, чи мені вдасться деякий час вертикально масштабувати одну машину? Чи буде це працювати з 10-кратними даними? 100x?

На це важко відповісти ґрунтовно. Можливо, вам краще вивчити загальні характеристики продуктивних запитів MySQL, щоб ви знали, чого можна очікувати; Звичайно, завжди можна зробити 20 дисків на сервері, щоб ви могли читати при 3 Гб / с або близько того. Але я думаю, ви після ретельної відповіді лише на програмне забезпечення.
usr

Відповіді:


4

Ви спробували зібрати більше даних та порівняти їх? 100 К рядків не має значення. Спробуйте 250 млн. Або 500 млн. Так, як ви очікуєте, що вам доведеться впоратися і подивитися, де є вузькі місця.

RDBMS може зробити багато речей, якщо ви уважно стежите за обмеженнями і спробуєте працювати з сильними сторонами системи. Вони надзвичайно хороші в одних речах, а в інших жахливі, тому вам потрібно буде експериментувати, щоб переконатися, що це правильно.

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

Що ви хочете зробити, це дослідити, як можна розподілити ваші дані. Чи є у вас великий набір даних із занадто великою кількістю перехресних посилань, щоб їх можна було розділити, чи є природні місця для їх поділу? Якщо ви можете розділити його, у вас не буде однієї таблиці з цілою купою рядків, але можливо багато значно менших. Менші таблиці, зі значно меншими індексами, як правило, працюють краще.

З точки зору обладнання, вам потрібно буде протестувати, щоб побачити, як працює ваша платформа. Іноді важливо пам'ять. В іншому випадку це дисковий ввід / вивід. Це дійсно залежить від того, що ви робите з даними. Вам потрібно буде приділити пильну увагу використанню процесора та шукати високий рівень IO чекати, щоб знати, де проблема полягає.

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


@tadman Дякую за пораду. Я усвідомлюю, що немає заміни для того, щоб насправді його спробувати. Я не оцінював це з 250М рядками, тому що спершу хотів переконатися, що в моєму підході очевидно нічого поганого. Здається, що немає. Крім того, отримати стільки даних і зробити це дещо реалістичним способом - це завдання, я ще не зрозумів, як її вирішити. У мене є кілька потенційних способів розділити дані. Я думаю, що наступного разу спробую збільшити свої дані та побачити, як це відбувається в різних контрольних пунктах - 1М, 10М, 100М тощо
xnickmx

1

Зведені таблиці.

Щодня обчислюйте сукупну інформацію для даних дня. Помістіть це у таблицю (зведення). Зробіть свої запити проти них. Легко в 10 разів швидше.

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

  • ПОКАЖІТЬ СТВОРИТИ ТАБЛИЦЮ (як зараз)
  • Розміри таблиць (які ви згадали)
  • Пропоновані SELECT

Деякі очевидні речі ...

  • BIGINT рідко є гарантійним. Він займає 8 байт. INT UNSIGNED займає 4 і дозволяє значення 0..4 млрд. А є MEDIUMINT тощо.
  • Кілька індексів таблиці "факт", як правило, є серйозною проблемою ефективності, особливо для INSERT. У вас там є проблеми?
  • DATETIME - 8 байт; TIMESTAMP - 4
  • Явні зовнішні ключові обмеження - це приємно, але дорого
  • ПРИЄДНАЙТЕСЯ може бути проблемою продуктивності; потрібно побачити SELECT і CREATE.
  • 100 Гб - хороший розмір для 'великої' бази даних MySQL; Я підозрюю, що це може працювати без Hadoop і т. Д. Зараз я маю справу з одним таким db - більшість сторінок інтерфейсу відповідає на секунду, хоча дані досить задіяні.
  • Чи будете ви в якийсь момент "очищати" дані? (Це призводить до основного випадку використання для PARTITIONing.)

"Менший -> більш кешований -> швидший


0

Якщо ви обслуговуєте свої дані на передньому кінці, якщо постійно немає зав’язків та вставок, ви дійсно не можете перемогти за допомогою тригерів для вставки в матеріалізовані подання, які синхронізуються із зворотним кінцем, але оптимізовані для обслуговування даних. Звичайно, у цих спрацьовувачах потрібно мінімізувати з'єднання тощо тощо. Однією з стратегій, яку я використав, є встановлення в чергу цих вставок / оновлень у проміжну таблицю, а потім надсилати їх пізніше щохвилини або близько того. Набагато простіше відправити один запис, ніж 4 Гб записів. 4 Гб даних потрібно тривати тривалий час, навіть якщо ви швидко знайдете потрібні записи.

Я згоден з тадманом. Найкраще - це профайлювати його з типом даних, які ви очікуєте, за системою, яку ви хочете.


Як я вже згадував у своєму дописі, перегляди залежать від запиту, який використовує чотири з'єднання між таблицями з десятками мільйонів записів, тому я не бачу, як допоможе матеріалізований вид.
xnickmx

Тригери можуть бути недостатньо швидкими для цієї бази даних розмірів. Скільки ВСТАВ в секунду відбувається?
Рік Джеймс

1
@xnickmx Якщо не так багато вставок / оновлень, тригери дозволяють легко / ефективно виконувати синхронізацію денормалізованих даних. Якщо потрібно вставити / оновити швидше, поставте їх у чергу з таким чином: blog.shlomoid.com/2008/04/… або запікайте власні. Таким чином, вам не доведеться приєднуватися до існуючих 100 мільйонів таблиць рядків, щоб отримати нові дані, оскільки коли спрацьовує тригер, ви скористаєтеся тим, що знаєте нові дані саме тоді і можете просто денормалізувати їх як частину tx або в черзі для денормалізації пізніше.
wes.stueve

@RickJames Погодився. Ви повинні врахувати кількість вставок для цієї стратегії та швидкість їх обробки.
wes.stueve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.