Одна таблица или многие? [закрытый]

Указатель NULL - это тот, который указывает на никуда. Когда вы разыскиваете указатель p, вы говорите «дайте мне данные в месте, хранящемся в« p ». Когда p является нулевым указателем, местоположение, хранящееся в p, является nowhere, вы говорите «Дайте мне данные в месте« нигде ». Очевидно, он не может этого сделать, поэтому он выбрасывает NULL pointer exception.

В общем, это потому, что что-то не было правильно инициализировано.

31
задан Community 23 May 2017 в 10:32
поделиться

15 ответов

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

Поиск и запросы не были бы более трудными - в конце концов, Вы могли просто создать представление, которое агрегировало всю информацию как в решении единственной таблицы, и затем запросите то представление далее.

Наличие все в одной таблице с большим количеством пустых указателей могло бы походить на простое решение, но на самом деле это приведет к большой проблеме. Например: С отдельными таблицами можно определить, который поля , потребовал для каждого BookReference, но если все находится в одной таблице, каждое поле должно быть nullable и поэтому дополнительным. Также было бы легче вставить недопустимые данные, как книжная ссылка, которая также ошибочно содержит непустое название журнала.

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

Редактирование: существуют некоторые комментарии относительно производительности. Очень трудно предположить заранее о производительности схем DB, потому что это часто неинтуитивно. Например, соединение между несколькими таблицами может легко быть быстрее, чем полное сканирование таблицы единственной таблицы - все это зависит от типа запроса, природы данных, доступные индексы и так далее. Кроме того, во многих системах баз данных можно использовать функции как осуществленные представления для оптимизации производительности для различных запросов, не ставя под угрозу логическую модель. "Денормализация для производительности" является главным образом грузовым культом в эти дни, по моему скромному мнению, если Вы не Google или Flickr.

35
ответ дан 27 November 2019 в 22:03
поделиться

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

Позволяет, говорят, что my-one-big-table похож на это:

1 идентификационный
2 тип
3 field-common-to-book-and-journal
4 field-specific-to-book
5 field-specific-to-journal

, Если я просто интересуюсь книгами, я могу создать представление, или просто sql, как это:

create view book as  
select id, field_common-to-book-and-journal, field-specific-to-book
from my-one-big-table
where type = 'book'

Так, легко моделировать это, данные находятся в отдельных таблицах, когда я хочу.

, Но, если я начинаюсь путем помещения данных в отдельные таблицы затем, я закончу тем, что писал SQL как это:

select id, field-common-to-book-and-journal from books
union
select id, field-common-to-book-and-journal from journal-articles
union
.... etc, for each type

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

, Если бы Вы следуете совету olavk затем, Ваш SQL для объединения типов в одном запросе закончил бы тем, что был похож на это:

select 
    common.id, 
    common.field-common-to-book-and-journal, 
    book.field-specific-to-book 
    journal.field-specific-to-journal
from common-table common
left outer join book-specific-table book on 
left outer join journal-specific-table journal on
... etc, for each type

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

3
ответ дан 27 November 2019 в 22:03
поделиться

Направляющие поддерживают наследование Единственной Таблицы и Полиморфные типы ActiveRecord. Я предложил бы изучить их - ActiveRecord имеет некоторые мнения о том, как база данных должна быть структурирована.

3
ответ дан 27 November 2019 в 22:03
поделиться

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

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

4
ответ дан 27 November 2019 в 22:03
поделиться

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

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

Составляют одну таблицу, которая будет содержать общие атрибуты для всех ссылок.

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

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

7
ответ дан 27 November 2019 в 22:03
поделиться

"жизнь легче с одной большой таблицей": я видел естественное следствие этого, будучи 100 + таблица столбца, и я могу сказать Вам, что нахожу, что эта никакая радость не работает с.

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

ссылка журнала требует и заголовка журнала и заголовка статьи и также номера страницы, тогда как книга требует издателя и года издания, которого статьи в журнале не требуют

..., который подразумевает следующие ограничения:

CONSTRAINT a_journal_must_have_a_journal_title
   CHECK ( type <> 'journal' OR journal_title IS NOT NULL );

CONSTRAINT a_journal_must_have_an_article_title 
   CHECK ( type <> 'journal' OR article_title IS NOT NULL );

CONSTRAINT a_journal_must_have_a_page_number 
   CHECK ( type <> 'journal' OR page_number IS NOT NULL );

CONSTRAINT a_journal_cannot_have_a_publisher 
   CHECK ( type <> 'journal' OR publisher IS NULL );

CONSTRAINT a_journal_cannot_have_a_publication_date 
   CHECK ( type <> 'journal' OR publication_date IS NULL );

CONSTRAINT a_book_cannot_have_a_journal_title 
   CHECK ( type <> 'book' OR journal_title IS NULL );

CONSTRAINT a_book_cannot_have_a_article_title 
   CHECK ( type <> 'book' OR article_title IS NULL );

CONSTRAINT a_book_cannot_have_a_page_number 
   CHECK ( type <> 'book' OR page_number IS NULL );

CONSTRAINT a_book_must_have_a_publisher 
   CHECK ( type <> 'book' OR publisher IS NOT NULL );

CONSTRAINT a_jbook_must_have_a_publication_date 
   CHECK ( type <> 'book' OR publication_date IS NOT NULL );

... и я подозреваю, что это - только верхушка айсберга!

Это - моя надежда, что после записи нескольких сотен таких ограничений у разработчика могут быть долгие размышления обо всех тех nullable столбцах :)

10
ответ дан 27 November 2019 в 22:03
поделиться

То, что я закончил тем, что делал в прошлом, использует подкатегории: наличие единственной таблицы со всем распространенный поля в нем и затем несколько таблиц, которые могут иметь zero-one отношения к "базовой" таблице.

пример ниже подобен чему-то, что мы используем "в дикой природе"; это в основном создает иерархическую структуру данных, где каждый узел может быть папкой или документом:

CREATE TABLE Node (
  Id int identity primary key,
  ParentId int null references Node.ParentId,
  Name varchar(50) not null,
  Description varchar(max) null
)

CREATE TABLE Doc (
  Id int primary key references Node.Id,
  FileExtension char(3) not null,
  MimeType varchar(50) not null,
  ContentLength bigint not null,
  FilePathOnDisk varchar(255)
)

CREATE TABLE Folder (
  Id int primary key references Node.Id,
  ReadOnly bit not null
)

Так Ваш GetFolder sproc сделает:

SELECT n.Id, n.ParentId, n.Name, n.Description, f.ReadOnly
FROM Node n 
JOIN Folder f ON n.Id = f.Id
WHERE f.Id = @Id

Это переводит вполне приятно в основанное на классах наследование:

public class Folder : Node
{
  public bool IsReadOnly { get; set; }
  ...etc
}
0
ответ дан 27 November 2019 в 22:03
поделиться

Olavk делает правильные замечания, и Corey дает большое подробное объяснение. Чтение информации Corey, тем не менее, дает мне заключение ответа Olavk. Следует иметь в виду, что в зависимости от того, что Вы делаете с информацией, можно закончить с 2 подготовками запрос. Найдите объект, затем для каждой ссылки, сделайте прямой выбор на том, что представляло интерес.

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

Организация хранилищ данных :)

0
ответ дан 27 November 2019 в 22:03
поделиться

Как насчет обоих? Имеют Ваш пирог и едят его также!

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

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

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

-1
ответ дан 27 November 2019 в 22:03
поделиться

Вы спрашиваете о нормализации базы данных. Jeff Atwood записал об этом в его сообщении , Возможно, Нормализация Не Нормальна . Это - хорошее чтение.

0
ответ дан 27 November 2019 в 22:03
поделиться

одна таблица и поле "типа" были бы моим предложением

0
ответ дан 27 November 2019 в 22:03
поделиться

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

1
ответ дан 27 November 2019 в 22:03
поделиться

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

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

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

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

2
ответ дан 27 November 2019 в 22:03
поделиться

Существует другая опция: не один я полностью подтвердил бы, но это - все еще другая опция:

Использование три таблицы:

refs (id, title, refType)
-- title of the reference, and what type of reference it is

fieldDef (id, fieldName, refType, dataType)
-- name of the field, which reference types it applies to, and
-- what type of data is stored in these fields (ISDN number, date, etc)

fields (refId, fieldId, value)
-- where you actually add data to the references.

refType может быть тип ссылки, и если Вы делаете это целым числом с увеличением значений полномочиями два (1, 2, 4, 8...) затем они могут быть добавлены вместе для создания битовой маски в fieldDef таблице.

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

Недостатки : это - материал, на котором сделан The Daily WTF. Избранные операторы могут стать очень сбивающими с толку и сложными. База данных не может выполнить проверку типа (например: для дат, и т.д.), и универсальное поле "значения" не будет оптимизирован для данных, сохраненных в нем.

1
ответ дан 27 November 2019 в 22:03
поделиться

Некоторое время назад я обсуждал эти вопросы со своим начальником. Конечно, я не смог доказать, что " иерархический многотабличный подход" (см. ответ olavk ) лучше, но я почувствовал это! Я бы всегда выбрал этот метод. Одна корневая таблица со всеми полями, которые имеют общие сущности, и 1-1 дочерние таблицы с полями, которые у них нет общих. При необходимости этот подход можно распространить на большее количество дочерних таблиц, если бизнес-логика и другие сущности будут что-то извлекать из этого. То есть, я не думаю, что с этим нужно переборщить.

Я также против создания отдельных «дочерних» таблиц без корневой таблицы, где каждая таблица имеет копию той же самой таблицы. поля. Я думаю, Кори » Ответ предлагает такой подход как пример плохой многостолочной модели, и он также его критикует. Я хотел бы добавить, что необходимость писать объединения - не главная проблема. Это вообще не проблема, поскольку большинство запросов к базе данных имеют много соединений, и это нормальное явление. Сложно создать отношения с другими таблицами - вам всегда нужны Id и TypeId, чтобы знать, какая таблица ссылается на них. В случае корневой таблицы вам нужен только идентификатор.

Сложно создать отношения с другими таблицами - вам всегда нужны Id и TypeId, чтобы знать, какая таблица ссылается на них. В случае корневой таблицы вам нужен только идентификатор.

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

0
ответ дан 27 November 2019 в 22:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: