Хранение атрибутов пользователя в пользовательской таблице
При создании базы данных с пользователями (которые имеют атрибуты, такие как религия), каков наилучший способ хранения этих атрибутов и возможных значений для них?
Вот методы и задачи:
Метод 1: Если у вас есть пользователь, скажем христианин, вы можете сохранить это значение в таблице пользователей в столбце под названием "религия". Проблема с этим методом заключается в том, что в таблице пользователей будет много, много случаев употребления слова "христианин", что кажется мне излишним.
Проблема 1: Кроме того, с помощью этого метода нигде в базе данных не хранятся все возможные значения, такие как "буддист", "мусульманин" и т. д. Это сделало бы заполнение выпадающего списка трудным, если не невозможным.
Метод 2: Еще один метод, который я придумал, заключается в индексации этих значений. Измените столбец " Религия "в таблице пользователей на" ReligionID " и пронумеруйте их. Христианин = 1, мусульманин = 2 и т. д. Затем установите связь внешнего ключа с другой таблицей со значениями подстановки.
Проблема 2: Проблема с этим методом заключается в том, что должно быть много, много таблиц, связанных с таблицей пользователей со значениями внешнего ключа для других подобных атрибутов, таких как цвет глаз. Хотя заполнение выпадающего списка было бы легко с помощью этого метода, это, кажется, создает слишком много соединений и кажется уродливым способом проектирования этой базы данных.
Как лучше всего это сделать? Не стесняйтесь придумывать свои собственные методы, если они не являются оптимальными. Спасибо!
4 ответа:
Нормализация баз данных-это все о компромиссах. То, как я смотрю на это, я всегда начинаю с максимально близкого к 3nf (т. е. Метод 2). Когда либо размер моих данных, либо мои требования к производительности изменяются ... Я рассматриваю денормализацию (т. е. метод 1).
Когда Вы дойдете до этого момента, ваши приложения должны взять на себя ответственность за целостность данных ... в зависимости от того, насколько вы контролируете клиентов базы данных, это может быть или не быть легко. Но именно поэтому ты ... получите большие деньги; -)
Я добавлю здесь еще один ответ, чтобы внести свой вклад в обсуждение. В комментарии Вы упомянули, что у вас может быть до 10-15 соединений, которые потребуются для получения всех отображаемых имен для внешних ключей.
Один из методов, который я часто использовал, чтобы обойти это, - это присоединиться к клиенту. Вот что я имею в виду:
- запросите таблицу без соединений ... это означает, что вы просто получите идентификаторы для многих ваших значений.
- во время отображения данных, в любое время, когда вам нужно отображение текстового значения попробуйте извлечь его из кэша.
- если его там нет, возьмите всю таблицу поиска прямо здесь и сейчас и кэшируйте ее в течение часа или дня (все, что имеет смысл).
- кэшированное значение может быть таким же простым, как словарь, поэтому вы можете взять словарь из кэша и вытащить строковое описание для отображения.
Это противоречит здравому смыслу ... но вы можете получить лучшее из обоих миров здесь. Отличная целостность данных из красиво оформленной базы данных, и отличная производительность, потому что вы не делаете никаких соединений на сервере.
Метод 1 будет работать нормально, если ваша форма позволяет произвольные записи (например, веры, которые вы еще не думали, где человек может ввести свою собственную веру или другой текст свободной формы).
Метод 2 будет работать нормально, если есть причина, по которой вы хотите поддерживать только определенный список верований и/или вы хотите иметь контроль над тем, когда добавляются новые верования.
Вы можете начать с метода 1, а затем преобразовать его в Метод 2, Если сочтете нужным. Зависит от вашего приложения, как его используют, и как это влияет на производительность и целостность: вопросы, на которые вы можете не знать ответа, пока люди действительно не начнут использовать его регулярно.
Вы можете сохранить атрибут пользователя, используя тип поля базы данных enum() для задания списка религий http://dev.mysql.com/doc/refman/5.0/en/enum.html . это поле будет принимать только значения, указанные при создании столбца. Это также упрощает добавление дополнительных типов путем изменения столбца в базе данных.
В PHP вы можете заполнить выпадающий список, используя эту функцию из http://akinas.com/pages/en/blog/mysql_enum чтобы получить массив значений перечисления в цикл:
function enum_select( $table , $field ){ $query = " SHOW COLUMNS FROM `$table` LIKE '$field' "; $result = mysql_query( $query ) or die( 'error getting enum field ' . mysql_error() ); $row = mysql_fetch_array( $result , MYSQL_NUM ); #extract the values #the values are enclosed in single quotes #and separated by commas $regex = "/'(.*?)'/"; preg_match_all( $regex , $row[1], $enum_array ); $enum_fields = $enum_array[1]; return( $enum_fields ); }