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

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

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

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

Очевидно, что одним из положительных моментов создания плоских таблиц является разделение данных (безопасность) и снижение скорости запросов. А если серьезно, какую выгоду я получу от этого? Я на самом деле не хочу 10000 таблиц и постоянно отбрасывать, изменять и добавлять, но если это будет лучше, чем я это сделаю... Мне просто нужен некоторый вклад.

Спасибо


person StratusBase LLC    schedule 01.12.2010    source источник
comment
Нормализуйте, пока не станет больно. :)   -  person shamazing    schedule 01.12.2010
comment
Не настоящий ответ ... но вы всегда можете использовать Википедию в качестве руководства. Вот схема базы данных Википедии: commons.wikimedia.org/wiki/File: Mediawiki-database-schema.png   -  person Dragontamer5788    schedule 01.12.2010
comment
@shamazing, затем денормализуйте, пока это не сработает. 80))   -  person Keng    schedule 01.12.2010
comment
Недавно я задал аналогичный вопрос, возможно, с другой точки зрения programmers.stackexchange.com/questions/212822/   -  person Yosi Dahari    schedule 10.10.2013


Ответы (7)


Практическое правило. Легче перейти от нормализованного к денормализованному, чем наоборот.

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

person Bob Palmer    schedule 01.12.2010
comment
По совпадению, я читал это stackoverflow.com/ вопросы/4301089/ - person Sathyajith Bhat; 01.12.2010
comment
Спасибо, Боб. Вы сделали очень хорошее замечание. Очень ценится. - person StratusBase LLC; 01.12.2010

Держите ваши данные нормализованными. Если вы правильно проиндексируете, вы не столкнетесь с проблемами производительности в течение очень долгого времени.

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

Единственная причина иметь плоские файлы - это когда ваши пользователи могут напрямую подключаться к БД (вы все равно можете использовать безопасность на уровне строк). Но в этом случае вы действительно повторно реализуете вариант phpmyadmin.

person Martin    schedule 01.12.2010
comment
+1 очень хороший ответ. Мартин, что делать, когда проблемы с производительностью начинают появляться спустя очень долгое время? Я никогда не работал с таким объемом данных/трафика, поэтому не знаю, что делать дальше. - person Sandeepan Nath; 01.12.2010
comment
а) Индексы работают очень быстро — поиск значений за 100 млн. таблицы строк, как правило, нет проблем, если соответствующие столбцы проиндексированы. Так что действительно есть большой запас, прежде чем вы столкнетесь с проблемами производительности. b) Вы можете разделить таблицы по диапазону, например, создать раздел на 1000 идентификаторов пользователей. Ваши запросы в основном будут влиять на один идентификатор пользователя и, следовательно, на один раздел, поэтому это должно увеличиваться почти линейно. - person Martin; 02.12.2010

...в этом приложении пользователи смогут создавать свои собственные формы с любым числовым полем...

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

Я думаю, вам нужно либо управлять этим шаг за шагом, либо позволить вашему странному флагу развеваться и просто продолжать покупать оборудование, чтобы не отставать от избиения, которое вы получите, когда пользователи действительно начнут вникать в это .... Наглядный пример , посмотрите, что происходит, когда пользователи начинают понимать, как создавать новые формы и представления в SharePoint... ЧУДО!! Разговор о масштабе ползучести !!

person Keng    schedule 01.12.2010
comment
Четко определите, какие поля/вводы они могут создавать. Ограничьте количество настроек, которые они могут сделать. Область действия определена для проекта и не должна меняться, пока я не заставлю это сделать. Спасибо за ваш вклад. - person StratusBase LLC; 01.12.2010
comment
@Steve B. Вы можете рассмотреть палитру универсальных полей, которые они могут добавить, которые нормализованы. Например: идентификатор сотрудника, который попадает в таблицу emp_table, чтобы люди не воссоздавали колесо. - person Keng; 01.12.2010
comment
У меня есть набор из 15 или около того входных данных, которые пользователь может использовать в форме, он может расти, но этого достаточно, чтобы делать почти все, что им нужно, они хранятся в статической таблице и связаны по идентификатору с пользовательскими формами. - person StratusBase LLC; 01.12.2010

Изменение схемы во время выполнения редко является хорошей идеей. Вам следует рассмотреть модель EAV (Entity-Attribute-Value).

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

person D'Arcy Rittich    schedule 01.12.2010
comment
Я никогда не слышал о EAV, но похоже, что оно похоже на решение, которое я предложил выше, используя таблицу с парами ключ/значение. Является ли мое предложенное выше решение похожим на решение EAV, которое вы предложили? Мне просто любопытно, потому что я хотел бы узнать больше о моделировании EAV. - person Madison Caldwell; 01.12.2010
comment
@Matt: да, это точно. В вашем случае E=form_id, A=key, V=value. Существуют модифицированные версии, в которых у вас есть дополнительные столбцы значений для разных типов данных, поэтому вы можете повысить эффективность с помощью индексов, агрегации и т. д., но это также усложняет запросы. - person D'Arcy Rittich; 01.12.2010

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

Если вы действительно хотите работать быстро, переключите схему на одну из баз данных с ключевым значением, например bigDB/couchDB и т. д. Это полностью денормализовано и очень-очень быстро.

person Byron Whitlock    schedule 01.12.2010

Я бы справился с этим, используя нормализованную, расширяемую таблицу «Свойство», например, как показано ниже:

Table: FormProperty
 id: pk
 form_id: fk(Form)
 key: varchar(128)
 value: varchar(2048)

Вышеприведенный пример — это всего лишь пример, но я использовал этот шаблон во многих случаях, и, как правило, он работает довольно хорошо. Единственная реальная проблема заключается в том, что вам нужно сериализовать значение как строку/varchar, а затем десериализовать его до того, что ему нужно, поэтому на клиенте ложится небольшая дополнительная ответственность.

person Madison Caldwell    schedule 01.12.2010
comment
Например, чтобы создать форму входа, вы можете: вставить в FormProperty(form_id, key, value) значения (1, 'email', '<некоторые xml или json, представляющие свойства поля>>'); вставить в FormProperty(form_id, key, value) значения (1, 'пароль', '‹fieldproperty›‹type›password‹/type›‹defaultvalue›‹/defaultvalue›‹/fieldproperty›'); - person Madison Caldwell; 01.12.2010
comment
В качестве альтернативы json/xml в приведенном выше примере вы можете создать дополнительные таблицы для свойств полей и связать их с помощью внешних ключей. - person Madison Caldwell; 01.12.2010

Нормализованный == быстрый поиск, проще поддерживать индексы, более медленные транзакции вставки (в нескольких строках)

Денормализованные == быстрые вставки, обычно это используется, когда вставок много (хранилищ данных, которые собирают и записывают хронологические данные)

person dexter    schedule 01.12.2010