Розбиття таблиць у MySQL. Гарна практика?


14

Я почав працювати над існуючим проектом, і попередній розробник розділив таблицю на 10 окремих таблиць з однаковими схемами, але різними даними.

Таблиці виглядають так:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

Первинний ключ - це ціле idполе. Додаток використовує алгоритм хешування ( idмод 10), щоб знати, до якої таблиці отримати доступ під час пошуку. Наприклад id= 10 призведе до [tableName_0].

У поєднанні таблиці мають, мабуть, 100 000 рядків, а темпи зростання відносно низькі.

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

Відповіді:


17

Я думаю, що всі надмірно ускладнюють це. Ключовий момент тут:

У поєднанні таблиці мають, мабуть, 100 000 рядків, а темпи зростання відносно низькі.

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

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


3

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

Якщо коротше, якщо ви працюєте з версією 5.1+, ви можете дозволити mysql зробити цей розділ за вас. Дивіться сторінку http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Якщо ви використовуєте 5.5, слід перевірити ці конкретні документи, оскільки ви знайдете деякі відмінності.

Є багато переваг у розділення. Однак це дійсно залежить від набору даних, що знаходиться під рукою, моделей доступу та способу їх індексації. Також майте на увазі, що мої наступні коментарі знаходяться в контексті розбиття mysql 5+, НЕ старих таблиць злиття mysql; хоча вони іноді обговорюються з точки зору розділів.

Деякі приклади:

  • Пряме (або хеширование) пряме базування на основі клавіші пошуку, яка часто доступна. Якщо ви майже завжди шукаєте первинний або інший унікальний ключ, тоді mysql може скоротити простір пошуку в коефіцієнті, скільки коли-небудь у вас розділів. Зауважте, однак це може бути згубним, якщо ви розділите один ключ, а потім часто шукаєте інший ключ. Якщо ви шукаєте за ключем, дані не розділяються, тоді він повинен БІЛЬШЕ шукати під час пошуку (по одному для кожного розділу, b / c відверто кажучи, він не знає, де дані)
  • Поміркуйте, чи були у вас тимчасові набори записів, які зростають за датою, і ви періодично обрізаєте попередній місяць. Якщо ви розділяєте за датою, ви можете просто скинути розділ, який так само швидко, як і опустити таблицю, незалежно від величини. Якщо ви повинні обрізати таку таблицю за датами, вам доведеться видати один або кілька DELETE запитів, де видаляється кожен окремий рядок. Мінус цього полягає в тому, що mysql не автоматично створює нові розділи, як тільки ви досягли максимальної дати, яку ви врахували в цьому сценарії; вам потрібні додаткові сценарії технічного обслуговування, побудовані на вашій частині, щоб додати розділи у міру необхідності.
  • Якщо ви використовуєте перевірку myisam, то відновлення коштів відбувається набагато швидше. Розглянемо таблицю мізаму 100G. Якщо ви хочете відновити збійну таблицю, вам знадобиться приблизно 100 Г запасного місця на диску. Якби він був розділений на 10 різних фрагментів однакового розміру, тоді вам потрібно лише 10 Г місця (і менше пам'яті key_sort_buffer для швидкого відновлення); але потрібно було б зробити ітерацію для кожного розділу.

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

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

EDIT

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


3

Те, що попередній розробник зробив для вас, - це власна реалізація розділу за хешем. MySQL буквально підтримує це від MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/uk/partitioning-hash.html

Я не можу придумати вагомих причин, тому реалізуйте свій власний розділ за хешем, а не покладайтеся на нативну версію [1]. Виконання змін схеми буде кошмаром.

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

[1] Однак для деяких інших типів розділів може бути доцільним прокрутка власного розділу. MySQL змушує вас зробити ключ вашого розділу частиною вашого первинного ключа та всіх унікальних індексів.


2

У відповідь на запитання:

полягає в тому, чи є це прийнятним рішенням чи ні

ІМХО, це здається непотрібним накладними. Ви можете просто індексувати та розділити одну таблицю належним чином, якщо в описі немає іншої інформації, яка не виявлена.

У відповідь на запитання:

... якщо це хороша практика в будь-якій ситуації

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

Наприклад, прикиньте таблицю веб-журналу, може мати форму:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Ваше рішення створює таблиці за потребою в базі даних веб-журналів:

weblogs.20120301
weblogs.20120302
weblogs.20120303

тощо.

Таким чином, дані залишаються доступними для пошуку та пошуку. Видобуток стає нормальним періодичним процесом. Безперервні операції не блокуються операціями зі старими даними.

У представленому вами сценарії ви все одно заблоковані в структуру, то чому б не використовувати єдину таблицю, оптимізовану для цієї мети? Зберігання рядків, засноване на алгоритмі, здається схематичним та схильним до помилок.


0

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

Тож питання полягає в тому: чи варто цей розкол для продуктивності чи це шкодить продуктивності?

Якщо у вас є транзакція, яка потребує блокування декількох рядків у кількох таблицях, і на ній є проблеми (наприклад, тупик або час очікування транзакції), можливо, вам захочеться об'єднати їх в одну таблицю і переписати SQL для усунення проблем.

Коли я замислююся над тим, щоб розділити таблицю, я брав до уваги компроміс між підвищенням продуктивності та складністю програмування.

У вашій ситуації зміна існуючого коду може бути довгостроковим рішенням, щоб полегшити підтримку коду. Я б запропонував спробувати мета-програмування. Наприклад, використовуючи StringTemplate для динамічного генерування SQL. Мені подобається генерувати SQL з двигуна метапрограмування, якщо модифікація існуючого коду занадто важка.


0

Коли вам потрібно зберігати файли в таблиці, використання цієї методології допомагає експортувати, відновлювати та відновлювати.

У мене таблиці з> 30 Gb, розподілені на 10 таблиць. Ці таблиці мають лише ідентифікатор - BLOB і мені легко зберігати. І я використовую MyISAM для збереження буфера INNODB.

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