MySQL: кілька таблиць або одна таблиця з багатьма стовпцями?


124

Тож це більше питання дизайну.

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

Чи слід мати декілька таблиць, розбитих на категорії відповідно до інформації, або я повинен мати лише одну таблицю з багатьма стовпцями?

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

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

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

Який звичайний спосіб це зробити?


Для наочності виправте мене, якщо я помиляюся, але я думаю, що "кілька таблиць" можна зрозуміти як посилання / асоціативна таблиця: en.wikipedia.org/wiki/Associative_entity
cellepo

1
Чи потрібна ця база даних для аналітичних цілей або для операційної / транзакційної обробки?
Олександр Радев

Відповіді:


112

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

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

Стаття Вікіпедії про нормалізацію бази даних може бути цікавою, оскільки вона глибоко обговорює причини цього:

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

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


Дякую за вашу відповідь, тому, прочитавши його, я думаю, що я говорив про ситуацію з інформацією "один на один", коли у користувача багато колонок один на один.
Xavier_Ex

@Xavier_Ex - Так, якщо є лише один стовпець на кожного користувача, то просто з однією величезною таблицею користувачів буде легше працювати (і набагато простіше оптимізувати двигун БД).
Брендан Лонг

Ваше відредаговане повідомлення надає більше корисної інформації! У мене є нове занепокоєння, що якщо деякі стовпці будуть часто оновлюватися, я повинен розміщувати їх в окремих таблицях? Наприклад, дата народження користувача не оновлюватиметься ніколи, але маркер заднього кінця через певний проміжок часу може бути недійсним і потребуватиме частого оновлення. Чи було б краще, якби я розділив таблиці таким чином, щоб поліпшити продуктивність? Зараз я поїду читати про вікі, про який ви згадали :)
Xavier_Ex

@Xavier_Ex - я б не рекомендував це. Ви отримуєте значно кращі показники роботи, коли можете шукати всі необхідні дані в одній таблиці (див. Статтю про денормалізацію). Приєднання дорого, тому що (1) вони вимагають пошуку даних у декількох місцях, що може включати пошуки на спінінг-диску, (2) зазвичай вимагають декількох індексів і певного злиття; (3) вони ускладнюють планування запитів, що не потрібен лише час, але також збільшується ймовірність того, що оптимізатор запитів отримає щось не так (а погано оптимізовані запити можуть бути дуже повільними).
Брендан Довгий

1
Нещодавно я зіткнувся з цією ж проблемою, оскільки таблиці MySQL InnoDB мають відносно невелику межу довжини (~ 8000 байт). У моїй проблематичній таблиці (дані із дуже тривалих страхових форм, понад 100 стовпців) у нас є кілька колонок varchar, всі UTF8. Тож ми легко заповнили межу ~ 8000 байт і отримували "помилку 139 від двигуна зберігання" весь час. Тож нам довелося розділити стіл. (Ми тестували новіший формат Barracuda, і він працював без розщеплення, але сервери нашого клієнта все ще використовують MySQL 5.0).
МВ.

12

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

Коли таблиці отримують занадто багато стовпців, ви можете зіткнутися з проблемами з фактичним розміром сторінки, на якій база даних зберігає інформацію. Або запис може бути занадто великим для сторінки, в результаті чого ви можете не створити або оновити конкретну запис, що робить користувачів нещасними, або ви можете (як мінімум, на SQL Server) дозволити певний переповнення типи даних (з набором правил, які потрібно шукати, якщо ви це робите), але якщо багато записів переповнять розмір сторінки, ви можете створити надзвичайні проблеми з продуктивністю. Тепер, як MYSQL обробляє сторінки та чи виникають у вас проблеми, коли потенційний розмір сторінки стає занадто великим - це те, що вам доведеться шукати в документації для цієї бази даних.


1
Ах різні голоси! Що завжди чудово. Дякуємо за вашу інформацію! Я переконуюсь, що мені це відомо, коли я роблю свої столи ... але я не знав, що мені доведеться спочатку знати про такі низькі рівні.
Xavier_Ex

4

Я маю хороший приклад. Занадто нормалізована база даних із таким набором відносин:

people -> rel_p2staff -> staff

і

people -> rel_p2prosp -> prospects

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

Така конструкція застосовується для всієї бази даних.

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

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

Рішенням буде мати пряме відношення до people -> staffтаpeople -> prospect


Цікаво буде знати, як відбулася відбудова? Ви в кінцевому підсумку спроектували щось подібне до успадкування однієї таблиці, де ви були typeістотою staffчи а prospect?
Coderama

1
Пішли з прямими стосунками люди -> персонал і люди -> перспектива, працює привабливість, проста у використанні, швидка запит.
Влад

4

Потрапив до цього, і коли хтось багато використовував MySQL, а недавно перейшов на Postgres, однією з головних переваг є те, що ви можете додавати JSON-об’єкти до поля в Postgres.

Отже, якщо ви перебуваєте в цій ситуації, вам не доведеться обов'язково вирішувати між однією великою таблицею з багатьма стовпцями та розділяти її, але ви можете об'єднати стовпці в об'єкти JSON, щоб зменшити її, наприклад, замість того, щоб адреса була 5 стовпцями, вона може просто бути одним. Ви також можете зробити запит і на цьому об’єкті.


як щодо його продуктивності при використанні об’єкта json під час запитів?
dagalti

1
@dagalti продуктивність добре для додатків, якими я користувався. Я не робив свого власного тестування, але це могло б вам стати в нагоді
moinhaque

3

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

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

Мінуси проектувати складніше, запити стають трохи складнішими

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


Дякую, що нагадали мені! Тож у моєму випадку я розглядав лише той випадок, коли кожен користувач не може мати більше, ніж один рядок, тому всі інформаційні поля є однозначними. Також користувач не може мати більше одного примірника одного і того ж елемента, оскільки я вважаю, що поняття одного елемента не може існувати в більш ніж одному місці. Щодо третього питання, так, я можу додати до таблиці більше елементів, але вони не порушать вимог, про які я згадував вище. Я думаю, що таблиця батьків / дітей є хорошою, коли я хочу пов’язати кілька рядків з одним користувачем, але в цьому випадку я хвилююся, що у користувача є багато стовпців один на один.
Xavier_Ex

навіть якщо всі елементи в даний час є один на один, це не унеможливлює потреби чи бажання мати батьківські / дочірні таблиці IMO. Ведення журналу змінених даних - це одне використання. ледачі завантаження об'єктів - це інше. в той час, як є користь для структури однієї таблиці, є переваги і для макетів батьків-батьків (хоча я бачив, що люди також впадають у крайність і з цими).
Брайан

1

Я вже робив якийсь дизайн бази даних. для мене це залежить від складності системи з управлінням базами даних; так, правда мати унікальні дані лише в одному місці, але насправді важко робити запити із надмірно нормалізованою базою даних з великою кількістю записів. Просто поєднайте дві схеми; скористайтеся однією величезною таблицею, якщо відчуваєте, що у вас буде велика кількість записів, які важко підтримувати так само, як facebook, gmail тощо. і використовувати різні таблиці для одного набору записів для простої системи ... ну це лише моя думка .. Я сподіваюся, що це могло б допомогти .. просто зробіть це ... ви можете це зробити ... :)


1
"використовуйте одну величезну таблицю, якщо у вас будуть масивні записи." Але Facebook, Google не зберігає дані користувачів в одній таблиці, вони розділили їх як багато таблиць.
Ямі Одімель

0

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


Дякую за інформацію, але вибачте, я не зовсім розумію вашу відповідь ... Я проведу пошук за двома схемами, про які ви згадали першими ...
Xavier_Ex

-4

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

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