#arrays #postgresql #database-design #denormalization
#массивы #postgresql #база данных-дизайн #денормализация
Вопрос:
В моем университете мне дали задание создать простую университетскую базу данных с несколькими таблицами типа student, departments и т.д. Был интересный момент, когда я делал отношения между студентами и классами, один студент может выбирать несколько классов, меня учили создавать третью таблицу с двумя FK, и она должна выглядеть следующим образом: Адам (id — 1) посещает курс математики (id — 5), и в третьей таблице запись будет (1, 5), и вот вопрос, почему мы должны предпочесть третью таблицу вместо массивов, для меня гораздо проще разместить классы студентов в качестве дополнительного столбца в student таблица. Вот пример, представьте таблицу student (id, name, age, arrayOfClassesID) (1, Adam, 20, [1,8,9,6,7])
.
P.S. Это не мое домашнее задание, я его уже выполнил, но для меня это действительно интересно
Комментарии:
1. Во-первых, у вас не может быть внешнего ключа, который гарантирует, что в этом массиве хранятся только допустимые идентификаторы классов
2. @a_horse_with_no_name, да, это первое, что пришло мне в голову. Но кроме этого, как насчет производительности, потому что, используя массивы, мы удаляем JOIN и, насколько я знаю, JOIN стоит дорого
3. Нет, объединения не «стоят дорого», это распространенное заблуждение. Вокруг этого построены реляционные базы данных. Единственный случай, когда массив имеет смысл, — это когда вы всегда считываете и записываете все элементы как одно значение и вам никогда не приходится искать отдельные элементы в массиве. Цитирую руководство » Массивы не являются наборами; поиск определенных элементов массива может быть признаком неправильного проектирования базы данных »
4. @a_horse_with_no_name, о, отлично, это действительно хороший ответ, поэтому, если я выберу всех студентов и их классы, массив будет иметь смысл, но если я сделаю что-то вроде выбора всех студентов, которые изучают математику и биологию, в этом случае массив будет плохой практикой. Я прав?
5. Использование
array
forFK
s приведет к проблемам с производительностью с точки зрения линейного поиска внутри массива. Более того, это затрудняет выполнение запросов
Ответ №1:
С теоретической точки зрения проблема заключается в том, что такой дизайн нарушает первую нормальную форму. Это имеет практические последствия:
-
Как прокомментировал a_horse_without_name, проблема номер один заключается в том, что у вас не может быть ограничений внешнего ключа на элементы массива.
-
Индексирование для быстрого поиска работает ограниченным образом с использованием индексов GIN и
@>
оператора. Поиск с помощьюLIKE
или>
не может быть оптимизирован. -
Поиск класса для всех учащихся будет менее эффективным, даже с индексом GIN, а запрос будет более сложным и менее интуитивно понятным.
-
Если вы хотите удалить класс для student, вам придется переписать весь массив. Возможно, здесь это не большая проблема, но с более длинными массивами это может повредить.
Использование таблицы сопоставления — это естественный способ сделать это в реляционной базе данных.