Какой дизайн базы данных лучше: больше таблиц или больше столбцов?

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

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

Итак, есть ли существенные преимущества для большего количества таблиц с меньшим количеством столбцов по сравнению с меньшим количеством таблиц с большим количеством столбцов?

18 ответов

Решение

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

  1. Благосклонность нормализации. Денормализация - это форма оптимизации со всеми необходимыми компромиссами, и к ней следует подходить с позиции YAGNI.
  2. Убедитесь, что клиентский код, ссылающийся на базу данных, достаточно отделен от схемы, чтобы при его переработке не требовалось серьезного изменения дизайна клиента (ов).
  3. Не бойтесь денормализовать, когда это дает явное преимущество для производительности или сложности запросов.
  4. Используйте представления или нисходящие таблицы для реализации денормализации, а не денормализации ядра схемы, если это позволяют объем данных и сценарии использования.

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

Это звучит не так как вопрос о таблицах / столбцах, а о нормализации. В некоторых ситуациях высокая степень нормализации ("больше таблиц" в данном случае) хороша и чиста, но обычно требуется большое количество JOIN для получения релевантных результатов. И с достаточно большим набором данных это может снизить производительность.

Джефф написал немного об этом относительно дизайна Stackru. Смотрите также пост Джеффа, на который ссылается Dare Obasanjo.

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

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

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

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

Это зависит от вашей базы данных. Например, MS SQL Server предпочитает более узкие таблицы. Это также более "нормализованный" подход. Другие двигатели могут предпочесть это наоборот. Мейнфреймы, как правило, попадают в эту категорию.

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

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

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

Как и все остальное: это зависит.

Не существует жесткого и быстрого правила относительно количества столбцов и количества таблиц.

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

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

Избегайте сложности, если это возможно. Например, если клиент может иметь только два адреса (а не произвольно много), то может иметь смысл просто хранить их все в одной таблице (CustomerID, Name, ShipToAddress, BillingAddress, ShipToCity, BillingCity и т. Д.).

Вот пост Джеффа на эту тему.

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

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

Будет ли клиенту разрешено иметь более 1 адреса? Если нет, то отдельная таблица для адреса не нужна. Если это так, то отдельная таблица становится полезной, потому что вы можете легко добавить больше адресов по мере необходимости, где становится сложнее добавить больше столбцов в таблицу.

Когда вы разрабатываете свою базу данных, вы должны быть как можно ближе к смыслу данных, а НЕ к вашему приложению!

Хороший дизайн базы данных должен стоять более 20 лет без изменений.

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

Лучше иметь несколько таблиц вместо нескольких столбцов и использовать представление, если вы хотите упростить ваш запрос.

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

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

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

Я думаю, что мой ответ будет, используйте ваше лучшее суждение.

Хм.

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

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

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

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

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

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

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

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

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

Суть в том, что подобные решения должны быть учтены самим приложением, прежде чем вы начнете снимать для повышения эффективности. ИМО.

Приятно видеть так много вдохновляющих и хорошо обоснованных ответов.

Мой ответ будет (к сожалению): это зависит.

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

То же самое верно для выбора между объектно-ориентированным подходом и другими вариантами.

Другие вопросы по тегам