Одиночная фиксированная таблица с несколькими столбцами и гибкими абстрактными таблицами

Мне было интересно, есть ли у вас сайт с десятком различных типов списков (магазины, рестораны, клубы, отели, события), которые требуют разных полей, есть ли смысл создавать таблицу со столбцами, определенными так: Пример магазина:

shop_id | name | X | Y | city | district | area | metro | station | address | phone | email | website | opening_hours

Или более абстрактный подход, подобный этому:

object_id | name        
---------------
1         | Messy Joe  
2         | Bate Motel 

type_id | name
---------------
1       | hotel
2       | restaurant


object_id | type_id
---------------
1         | 2
2         | 1

field_id | name           | field_type
---------------
1        | address        | text
2        | opening_hours  | date 
3        | speciality     | text

type_id | field_id
---------------
1       | 1
1       | 2
2       | 1
2       | 3

object_id | field_id | value
1         | 1        | 1st street....
1         | 3        | English Cuisine

Конечно, он может быть более абстрактным, если значение предопределено (пример: специальности могут иметь свой собственный список)

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

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

Ответ 1

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

Предварительное разрешение

  • Этикетки
    В профессии, которая требует точности, важно, чтобы мы использовали точные ярлыки, чтобы избежать путаницы, и чтобы мы могли общаться, не используя длинные описания и квалификаторы.
    .
    То, что вы разместили как FixedTables, Не нормировано. Достаточно справедливо, это может быть попытка третьей нормальной формы, но на самом деле это плоский файл, Unnormalised (не "denormalised" ). То, что вы опубликовали как AbstractTables, является, точнее, Entity-Attribute-Value, который является почти, но не совсем, Шестой нормальной формой и, следовательно, более нормализован, чем 3NF. Предположим, что это сделано правильно, конечно.

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

    • Чтобы быть Denormlaised, он должен быть сначала нормализован, а затем нормализация немного отступила по какой-то причине. Поскольку он не нормализуется в первую очередь, он не может быть Denormalised. Это просто ненормализованный.

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

    • Нормализованные структуры работают намного лучше, чем ненормализованные структуры. Более нормализованные структуры (EAV/6NF) работают лучше, чем менее нормализованные структуры (3NF/5NF).

    • Я согласен с тягой OMG Ponies, но не с их метками и определениями

    • вместо того, чтобы говорить "не надо" денормализовать "если не нужно", я говорю: "Нормализовать добросовестно, период" и "если есть проблема с производительностью, вы не нормализовались правильно". ,
  • Wiki
    Записи re Normal Forms и Normalization являются полной шуткой. В частности, определения неверны; они путают нормальные формы; они не понятны в процессе нормализации; и они дают равный вес абсурдным или сомнительным НФ, которые были развенчаны давно. В результате Wiki добавляет уже запутанный и редко понимаемый предмет. Так что не тратьте свое время. .
    Однако, чтобы продвигаться вперед, без этой ссылки, представляющей собой помеху, позвольте мне сказать это.

    • Определение 3NF является стабильным и не изменилось.
    • Существует много путаницы NF между 3NF и 5NF. Истина заключается в том, что это область, которая развивалась в течение последних 15 лет; и многие организации, ученые, а также продавцы с их продуктами с ограничениями, подскочили, чтобы создать новую "нормальную форму" для подтверждения своих предложений. Все служащие коммерческие интересы и академически необоснованные. 3NF в своем первоначальном непереполненном состоянии, предназначенном и гарантированном определенными атрибутами.
    • Общая сумма, 5NF сегодня, то, что 3NF планировалось 15 лет назад, и вы можете пропустить коммерческий подшучивание и двенадцать или около того "специальных" (коммерческих и псевдоакадемических) НФ между ними, некоторые из которых идентифицированы в Wiki, и даже в путаных терминах.
      ,
  • Поскольку вы смогли понять и реализовать EAV в своем посте, вам не составит труда понять следующее. Конечно, настоящая реляционная модель - это предварительные, сильные клавиши и т.д. Пятая нормальная форма, так как мы пропускаем четвертый:

    • Третья нормальная форма
      • который в простых окончательных терминах, каждый неявный столбец в каждой таблице имеет отношение 1:1 к первому ключу таблицы,
      • и без каких-либо других неключевых столбцов
    • Нулевое дублирование данных (результат, если нормализация продвигается усердно, не достигается только разведкой или опытом или работает над ней как цель без формального процесса)
    • no Update Anomalies (при обновлении столбца где-то вам не нужно обновлять тот же столбец, расположенный где-то в другом месте, столбец существует в одном и только одном месте). ,
  • Шестая нормальная форма - это, конечно, пятая нормальная форма плюс:

    • Устранение отсутствующих данных (столбцов). Это единственное истинное решение проблемы Null (также называемое "Обработка недостающих значений" ), и результатом является база данных без Nulls. (Это можно сделать на 5NF со стандартами и Null-заменителями, но это не оптимально.) Как вы интерпретируете и отображаете недостающие значения - это еще одна история. ,
  • EAV против шестой нормальной формы
    Все базы данных, которые я написал, кроме одного, являются чистыми 5NF. Я работал с (администрировал, исправил, улучшил) пару баз данных EAV, и я реализовал одну настоящую базу данных 6NF. EAV - это свободная реализация 6NF, часто выполняемая людьми, которые не имеют четкого понимания нормализации и NF, но которые могут видеть ценность и нуждаются в гибкости EAV. Вы - прекрасный пример. Разница в том, что: потому что он свободен, и потому что у разработчиков нет ссылки (6NF), чтобы быть верной, они только реализуют то, что им нужно, и они пишут все это в коде; что в конечном итоге является несогласованной моделью.
    .
    Принимая во внимание, что чистая реализация 6NF имеет чистую академическую контрольную точку, и, следовательно, она обычно более жесткая и последовательная. Обычно это отображается в двух видимых элементах:
    • 6NF имеет каталог, содержащий метаданные, и все определяется в метаданных, а не в коде. EAV не имеет одного, все в коде (разработчики отслеживают объекты и атрибуты). Очевидно, что каталог упрощает добавление столбцов, навигацию и позволяет создавать утилиты.
    • 6NF при понимании, обеспечивает истинное решение проблемы Null. EAV, поскольку они отсутствуют в контексте 6NF, обрабатывают недостающие данные в коде, непоследовательно или хуже, позволяют Nulls в базе данных. Разработчики 6NF запрещают Nulls и обрабатывают отсутствующие данные последовательно и элегантно, не требуя конструктов кода (для обработки Null, вам все равно придется кодировать недостающие данные, конечно).
      .
      Например. Для баз данных 6NF с каталогом у меня есть набор procs, который будет генерировать SQL, необходимый для выполнения всех SELECT, и я предоставляю Views в 5NF для всех пользователей, поэтому им не нужно знать или понимать базовую структуру 6NF, Они выгнали из каталога. Таким образом, изменения легки и автоматизированы. Типы EAV делают это вручную, из-за отсутствия каталога.

Теперь мы можем запустить

Обсуждение

"Конечно, это может быть более абстрактным, если значение предопределено (пример: специальности могут иметь свои собственные список)"

Конечно. Но не слишком "абстрактные". Поддерживайте согласованность и реализуйте такие списки в том же режиме EAV (или 6NF), что и другие списки.

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

  • Соединения являются пешеходными в реляционных базах данных. Проблема не в базе данных, проблема в том, что SQL является громоздким при обработке объединений, особенно составных ключей.
  • Базы данных EAV и 6NF имеют больше объединений, которые так же, как и пешеходы, не больше и не меньше. Если вам нужно каждый раз закодировать каждый SELECT вручную, конечно, громоздкий становится очень громоздким.
  • Вся проблема может быть устранена путем (а) перехода с 6NF через EAV и (b) реализации каталога, из которого вы можете (c) генерировать все базовые SQL. Устраняет и целый класс ошибок.
  • Это распространенный миф о том, что Joins каким-то образом стоит. Полностью ложно. Присоединение реализовано во время компиляции, нет ничего существенного для "стоимости" циклов ЦП. Проблема заключается в размере соединяемых таблиц, а не стоимости соединения между этими же таблицами. Объединение двух таблиц с миллионами строк в каждом правильном соотношении PK⇢FK, каждое из которых имеет соответствующие индексы (уникальное на родительской стороне [FK], уникальное на стороне ребенка) мгновенно;; где индекс Child не уникален, но по крайней мере ведущий столбец действителен, он медленнее; где нет полезного индекса, конечно, это очень медленно. Ничто из этого не связано с стоимостью соединения. Когда много строк возвращаются, узким местом будет сеть и макет диска; а не обработки соединения.
  • Поэтому вы можете получить как "сложный", как вам нравится, нет никакой стоимости, SQL может справиться с этим.

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

  • 5NF (или 3NF для тех, кто не сделал прогрессию) - это самый простой и лучший, с точки зрения внедрения, простота использования (разработчики, а также пользователи), обслуживание. Недостатком является то, что каждый раз, когда вы добавляете столбец, вам нужно изменить структуру базы данных (таблица DDL). Это хорошо, это некоторые случаи, но не в большинстве случаев, из-за контроля изменений на месте, довольно обременительны. Во-вторых, вам нужно изменить существующий код (обработка кода с использованием нового столбца не учитывается, поскольку это является императивом): где реализуются хорошие стандарты, которые минимизируются; где они отсутствуют, область непредсказуема.

  • EAV (это то, что вы опубликовали), позволяет добавлять столбцы без изменений DDL. Это единственная причина, по которой люди выбирают ее. (код, обрабатывающий новый столбец, не учитывается, потому что это обязательно). Если он будет реализован хорошо, он не повлияет на существующий код; если нет, то будет. Но вам нужны разработчики с поддержкой EAV. Когда EAV реализуется плохо, это отвратительно, хуже, чем 5NF сделано плохо, но не хуже, чем Unnormalised, что большинство баз данных там (искажено как "Denormalised for performance" ). конечно, еще важнее (чем в 5NF/3NF) придерживаться сильного контекста транзакций, потому что столбцы гораздо более распределены. Аналогичным образом, важно сохранить декларативную ссылочную целостность: беспорядки, которые я видел, были во многом обусловлены тем, что разработчики удаляли DRI, потому что он стал "слишком трудно поддерживать", результат, как вы можете себе представить, был одним из матери данных куча с повторяющимися строками 3NF/5NF и столбцами по всему месту. И непоследовательная обработка Null.

  • Нет никакой разницы в производительности, если предположить, что сервер был настроен по назначению. (Хорошо, существуют определенные оптимизации, которые возможны только в 6NF, которые невозможны в других NF, но я думаю, что это выходит за рамки этой темы.) И снова EAV сделал плохо, может вызвать ненужные узкие места, не более, чем Unnormalised.

  • Конечно, если вы идете с EAV, я рекомендую больше формальности; купите полный бросок; идти с 6NF; реализовать каталог; утилиты для создания SQL; Просмотры; обрабатывать данные без вести последовательно; полностью устранить Nulls. Это снижает вашу уязвимость до качества ваших разработчиков; они могут забыть о эзотерических исследованиях EAV/6NF, использовать Views и сосредоточиться на логике приложения.

Простите длинный пост.

Ответ 2

В вашем вопросе вы представили одновременно по крайней мере две основные проблемы. Этими двумя проблемами являются E-A-V и gen-spec.

Во-первых, позвольте говорить о E-A-V. Ваша последняя таблица (object_id, field_id, value) по существу является E-A-V. Существует потенциал роста E-A-V и недостаток E-A-V. Поверхность состоит в том, что структура настолько универсальна, что она может вмещать практически любую совокупность данных, описывающих практически любой предмет. Это означает, что вы можете приступить к проектированию и реализации без анализа данных и не понимать предмет, а не беспокоиться о неправильных предположениях. Нижняя сторона заключается в том, что во время поиска вы должны выполнить анализ данных, который вы пропустили, прежде чем строить базу данных, чтобы придумать запросы, которые означают что угодно. Это гораздо серьезнее, чем просто эффективность поиска. Но у вас также будут ужасные проблемы с эффективностью поиска. Есть только два способа узнать об этой ловушке: жить через нее или читать об этом от тех, кто имеет. Я рекомендую чтение.

Во-вторых, у вас есть случай gen-spec. Ваша таблица (object_id, type_id) захватывает шаблон gen-spec (обобщение-специализация) вместе со связанными таблицами. Если бы мне пришлось обобщать между гостиницами и ресторанами, я мог бы назвать это "публичными размещениями" или "местами". Но я не уверен, что понимаю ваше дело, и вы можете ездить за чем-то еще более общим, чем предлагают эти два названия. В конце концов, вы включили "события" в свой список, и событие не является местом встречи в моем сознании.

Я упомянул других людей о чтении на gen-spec и реляционной модели в предыдущих ответах.
 Когда две таблицы очень похожи, когда их следует комбинировать?

Но я стесняюсь отослать вас в том же направлении, потому что мне не ясно, что вы хотите создать реляционную модель данных, прежде чем строить свою базу данных. Реляционная модель тела данных и модель E-A-V тех же данных почти полностью противоречат друг другу. Мне кажется, что вам нужно сделать этот выбор, прежде чем вы даже изучите, как выразить генную спецификацию в реляционной модели данных.

Ответ 3

"Абстрактный" подход более известен как "Нормализация", выглядит как 3-я Нормальная форма (3NF).

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

Ответ 4

Как у вас есть списки, представленные в коде? Я бы предположил Listing как супертип, с Shop, Restuarant и т.д. Как подтипы?

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

  • Вариант 1: одиночная таблица для каждого подтипа, с общими атрибутами, повторяющимися в каждая таблица (имя, идентификатор и т.д.).
  • Вариант 2: одиночная таблица для всех объектов (подход с одной таблицей)
  • Вариант 3: таблица для супертипа и по одному для каждого подтипа

Нет универсально правильного решения. Мое предпочтение обычно начинается с варианта 3; он обеспечивает интуитивную структуру для работы, довольно хорошо нормируется и может быть легко расширена. Это означает единственное соединение для извлечения каждого экземпляра, но RDBMS хорошо оптимизированы для выполнения объединений, поэтому на практике это не вызывает проблем с производительностью.

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

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

Какой выбор действительно подходит к пониманию деталей вашей проблемы. Я бы предложил немного прочитать варианты: эта статья - хорошее место для начала.

HTH

Ответ 5

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

{
   "id": 1,
   "type":"Restaurant",
   "name":"Messy Joe",
   "address":"1 Main St.",
   "tags":["asian","fusion","casual"]
}