Консолидация таблиц с однозначными отношениями - PullRequest
6 голосов
/ 28 апреля 2011

У меня есть 3 таблицы MySQL для системы членства.

  • users: минимальное требование быть пользователем, относится только к информации об учетной записи (электронная почта, пароль, is_activation и т. Д.)
  • user_profiles: Персональная информация, предоставленная пользователем (имя, адрес, телефон ...)
  • user_member_profiles: информация строго контролируется администраторами (регистрационный сбор оплачен, собрания посещены и т.

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

Вариант 1: Оставьте это так и продолжайте делать JOIN с и утомительно UPDATE с (этот фрагмент данных идет в эту таблицу, этот фрагмент идет в другой и т. Д. ) * * тысяча двадцать-один. Больше работы для меня, но, может быть, это имеет больше смысла?

Вариант 2: Объедините все в один стол.

Я бы предположил, что использование одной таблицы будет быстрее, нет необходимости объединять таблицы. Может это зависит от данных? Каждая таблица имеет около 12-20 полей, поэтому объединенная таблица будет большой.

Каждый пользователь имеет не более 1 профиля из каждой таблицы, но может вообще не иметь профиля (или может иметь только 1 всего).

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

Каков правильный подход к этому с точки зрения производительности, дизайна или организации?

Ответы [ 6 ]

9 голосов
/ 28 апреля 2011

Другим фактором, который следует учитывать при использовании широкой таблицы (много столбцов), является влияние на кэш RDBMS. Любой хороший разработчик знает, что вы не делаете «выбор * из таблицы», поскольку он будет передавать ненужные данные по сети от СУБД к клиенту. Но аналогичный эффект может произойти между диском и оперативной памятью, а также повлиять на объем пространства в оперативной памяти, необходимый для кэширования таблицы.

Большинство СУБД выделяют определенный объем памяти для кэширования данных, тем самым сокращая чтение с физического диска и ускоряя реакцию пользователя. Это буферный кеш в Oracle или SQL Server

Если у вас есть широкая таблица и вы выполняете запрос в форме «выберите столбец col1, col2, col3 из таблицы», СУБД загрузит полные строки в ОЗУ (а не столбцы с 1 по 3). При этом он устареет из старых кэшированных данных. Если ваша таблица широкая и вы загружаете 50 столбцов, вам, конечно, требуется больше оперативной памяти, чем для того же числа строк * узкой таблицы. Это может оказать заметное влияние на производительность РСУБД.

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

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

2 голосов
/ 28 апреля 2011

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

2 голосов
/ 28 апреля 2011

Вам не нужно использовать столько объединений для получения данных.

Вы можете иметь VIEW, чтобы показать, например, все столбцы из users и user_profiles:

CREATE VIEW users2 AS
( SELECT u.id
       , u.email
       , u.password
       , u.is_activated
       , p.name
       , p.address
       , p.phone
  FROM users u
    LEFT JOIN user_profiles p
      ON u.id = p.id
)

и используйте этот VIEW в запросах, которым требуются данные из обеих таблиц. Еще один ВИД для всех 3 таблиц и т. Д.

2 голосов
/ 28 апреля 2011

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

1 голос
/ 28 апреля 2011

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

  • , если у каждого пользователя несколько профилей, разделяйте данные пользователя и профиля;используйте столбец в таблице профиля (много сторон связи), чтобы сослаться на первичный ключ пользовательской таблицы.
  • , если у каждого человека есть профиль (то есть один или нет), используйте две таблицытаким же образом, но для облегчения объединений используйте один и тот же первичный ключ в обеих таблицах.Цель состоит в том, чтобы избежать таблиц с большим количеством пустых строк.Еще один способ думать об этом - это то, что профиль наследуется от человека - и поэтому использует таблицу добавленных данных с тем же ключом.

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

0 голосов
/ 28 апреля 2011

Если у вас не возникают странные проблемы с производительностью, у вас должна быть только одна таблица.

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

Подобные проблемы с производительностью, о которых все желают, а их не так много ...

...