MySQL: несколько таблиц или одна таблица со многими столбцами?

125

Так что это скорее вопрос дизайна.

У меня есть один первичный ключ (скажем, идентификатор пользователя), и у меня есть масса информации, связанной с этим пользователем.

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

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

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

Я новичок в проектировании баз данных, поэтому какой подход лучше и каковы плюсы и минусы?

Как это обычно делается?

Xavier_Ex
источник
Для ясности поправьте меня, если я ошибаюсь, но я думаю, что "несколько таблиц" можно понимать как ссылку / ассоциативную таблицу: 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 обрабатывает страницы и есть ли у вас проблемы, когда потенциальный размер страницы становится слишком большим, вам придется искать в документации для этой базы данных.

HLGEM
источник
1
Ах разные голоса! Что всегда здорово. Спасибо за информацию! Я позабочусь об этом, когда буду составлять свои таблицы ... но я не знал, что мне нужно знать о таких низкоуровневых материалах изначально.
Xavier_Ex
4

У меня есть хороший пример. Чрезмерно нормализованная база данных со следующим набором отношений:

people -> rel_p2staff -> staff

и

people -> rel_p2prosp -> prospects

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

Такой дизайн сохраняется для всей базы данных.

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

Индексирование и все низко висящие плоды были израсходованы в прошлом году, все запросы оптимизированы до совершенства. Это конец пути для конкретного нормализованного дизайна, и теперь одобренное руководство перестроит все приложение, которое зависит от него, а также реструктуризует базу данных в течение 6 месяцев. $$$$ Ой.

Решением будет прямая связь между people -> staffиpeople -> prospect

Влад
источник
Было бы интересно узнать, как прошла перестройка? Вы в конечном итоге разработали что-то похожее на наследование одной таблицы, где у вас было typeсущество a staffили a prospect?
Coderama
1
Пошел с людьми прямого отношения -> персонал и люди -> перспектива, работает шарм, простой в использовании, быстрый запрос.
Влад
4

Я наткнулся на это, и как человек, который раньше много использовал MySQL, а затем недавно перешел на Postgres, одним из больших преимуществ является то, что вы можете добавлять объекты JSON в поле в Postgres.

Поэтому, если вы находитесь в этой ситуации, вам не обязательно выбирать между одной большой таблицей с множеством столбцов и ее разделением, но вы можете объединить столбцы в объекты JSON, чтобы уменьшить его, например, вместо адреса, равного 5 столбцам, он может просто Будь один. Вы также можете запросить этот объект.

moinhaque
источник
как насчет производительности при использовании объекта json во время запроса?
dagalti
1
@dagalti производительность нормальная для приложений, в которых я его использовал. Я не проводил свой собственный сравнительный анализ, но он может быть вам полезен
moinhaque
3

Задайте себе эти вопросы, если вы поместите все в одну таблицу, будет ли у вас несколько строк для этого пользователя? Если вам нужно обновить пользователя, хотите ли вы вести контрольный журнал? Может ли пользователь иметь более одного экземпляра элемента данных? (например, номер телефона). Будет ли у вас случай, когда вы захотите добавить элемент или набор элементов позже? если вы ответите «да», то, скорее всего, вы захотите иметь дочерние таблицы с отношениями внешнего ключа.

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

Минусы: сложнее дизайн, запросы становятся немного сложнее

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

Брайан
источник
Спасибо, что напомнили! Поэтому в моем случае я рассматривал только случай, когда у каждого пользователя не может быть более одной строки, поэтому все информационные поля взаимно однозначны. Также у пользователя не может быть более одного экземпляра одного и того же элемента, поскольку я считаю, что концепция одного элемента не может существовать более чем в одном месте. Что касается третьего вопроса, да, я мог бы добавить в таблицу больше элементов, но они не нарушат требований, упомянутых выше. Я думаю, что родительская / дочерняя таблица хороша, когда я хочу связать несколько строк с одним пользователем, но в этом случае меня беспокоит то, что у пользователя есть много столбцов один к одному.
Xavier_Ex
даже если все элементы в настоящее время один к одному, это не устраняет необходимости или желания иметь родительские / дочерние таблицы IMO. Одно из применений - ведение журнала измененных данных. ленивая загрузка объектов - другое. Хотя есть преимущества для единой структуры таблицы, есть преимущества и для родительских дочерних макетов (хотя я видел, как люди доходили до крайностей и с ними).
Брайан
1

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

Кристофер
источник
1
«используйте одну огромную таблицу, если у вас будет много записей…» Но Facebook, Google не хранят пользовательские данные в одной таблице, они разделяют их как можно больше таблиц.
Yami Odymel
0

Обычный способ сделать это - использовать разные таблицы, как в схеме «звезда» или в схеме «снежинка». Как бы то ни было, я бы основал эту стратегию как двоякую. Я верю в теорию, согласно которой данные должны существовать только в одном месте, там для схемы, которую я упомянул, будет хорошо работать. Тем не менее, я также считаю, что для механизмов отчетности и наборов бизнес-аналитики столбчатый подход был бы чрезвычайно полезен, поскольку он больше поддерживает потребности в отчетности. Колоночные подходы, подобные тем, что используются в infobright.org, имеют огромный прирост производительности и сжатия, что делает использование обоих подходов невероятно полезным. Многие компании начинают понимать, что наличие только одной архитектуры базы данных в организации не поддерживает весь спектр их потребностей. Многие компании реализуют концепцию наличия нескольких архитектур баз данных.

Крэйг Тромбли
источник
Спасибо за информацию, но извините, я не совсем понимаю ваш ответ ... Я
выполню
-4

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

user8081853
источник