одна фиксированная таблица с несколькими столбцами против гибких абстрактных таблиц - PullRequest
27 голосов
/ 25 октября 2010

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

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

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

object_id | name        
---------------
1         | Messy Joe's  
2         | Bate's 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

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

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

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

Ответы [ 5 ]

78 голосов
/ 25 октября 2010

Определенные проблемы необходимо прояснить и решить до . Мы можем вступить в разумное обсуждение.

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

  1. Ярлыки
    В профессии, которая требует точности, важно, чтобы мы использовали точные ярлыки, чтобы избежать путаницы и чтобы мы могли общаться без использования длинных описаний и определителей.
    .
    То, что вы опубликовали как FixedTables, это Ненормализовано .Справедливо, это может быть попытка создания формы в третьем нормальном состоянии, но на самом деле это обычный файл, ненормализованный (не «денормализованный»). То, что вы разместили в виде AbstractTables, если быть точным, Entity-Attribute-Value , которая является почти, но не совсем, шестой нормальной формой и, следовательно, более нормализована, чем 3NF. Конечно, при условии, что все сделано правильно.

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

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

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

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

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

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

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

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

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

Теперь мы можем начать

Обсуждение

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

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

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

  1. Объединения являются пешеходами в реляционных базах данных. Проблема не в базе данных, а в том, что SQL громоздок при обработке соединений, особенно составных ключей.
  2. Базы данных EAV и 6NF имеют больше соединений, которые, как и пешеходные, не больше, не меньше. Если вам приходится кодировать каждый SELECT вручную, конечно, громоздкость становится действительно громоздкой.
  3. Вся проблема может быть устранена путем (а) перехода с 6NF на EAV и (б) внедрения каталога, из которого вы можете (с) генерировать все основные SQL. Устраняет также целый класс ошибок.
  4. Это распространенный миф, что соединения как-то имеют цену. Совершенно неверно. Объединение реализуется во время компиляции, нет ничего существенного в том, чтобы «стоить» циклы ЦП. Проблема заключается в размере объединяемых таблиц, а не в стоимости объединения этих таблиц. Соединение двух таблиц с миллионами строк в каждой по правильному отношению PK⇢FK, каждая из которых имеет соответствующие индексы (уникальный со стороны родителя [FK]; уникальный со стороны ребенка), происходит мгновенно; ; где дочерний индекс не уникален, но по крайней мере ведущий столбец является действительным, он медленнее; где нет полезного индекса, конечно, это очень медленно. Ничто из этого не имеет отношения к стоимости присоединения. Если возвращено много строк, узким местом будет сеть и структура диска; не обработка объединения.
  5. Таким образом, вы можете делать все так, как вам угодно, без всяких затрат, SQL может справиться с этим.

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

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

  2. EAV (то, что вы опубликовали), позволяет добавлять столбцы без изменений DDL. Это единственная причина, по которой люди выбирают это. (код, обрабатывающий новый столбец, не считается, потому что это обязательно). При правильной реализации это не повлияет на существующий код; если нет, то будет. Но вам нужны разработчики с поддержкой EAV. Когда EAV реализован плохо, он отвратителен, хуже, чем 5NF, плохо, но не хуже, чем Ненормализованный, который есть в большинстве баз данных (искаженный как «Денормализованный для производительности»). конечно, даже более важно (чем в 5NF / 3NF) поддерживать сильный контекст транзакции, потому что столбцы гораздо более распределены. Точно так же важно сохранить декларативную ссылочную целостность: увиденные мною беспорядки во многом были связаны с удалением DRI разработчиками, потому что его стало «слишком сложно поддерживать», в результате, как вы можете себе представить, была одна мать данных куча с дубликатами 3NF / 5NF строк и столбцов повсюду. И непоследовательная обработка Null.

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

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

9 голосов
/ 25 октября 2010

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

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

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

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

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

3 голосов
/ 16 февраля 2017

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

{
   "id": 1,
   "type":"Restaurant",
   "name":"Messy Joe",
   "address":"1 Main St.",
   "tags":["asian","fusion","casual"]
}
2 голосов
/ 25 октября 2010

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

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

1 голос
/ 25 октября 2010

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

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

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

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

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

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

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

НТН

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