Предположим, я создаю блог, в котором я хочу иметь посты и комментарии. Поэтому я создаю две таблицы: таблицу «posts» с автоинкрементным целочисленным столбцом «id» и таблицу «comments» с внешним ключом «post_id».
Затем я хочу выполнить то, что, вероятно, будет моим самым распространенным запросом, а именно: получить сообщение и все его комментарии. Будучи довольно новым для реляционных баз данных, подход, который кажется мне наиболее очевидным, заключается в написании запроса, который будет выглядеть примерно так:
SELECT id, content, (SELECT * FROM comments WHERE post_id = 7) AS comments
FROM posts
WHERE id = 7
Который дал бы мне идентификатор и содержание сообщения, которое я хочу, вместе со всеми соответствующими строками комментариев, аккуратно упакованными в массив (вложенное представление, которое вы использовали бы в JSON). Конечно, SQL и реляционные базы данных не работают таким образом, и самое близкое, что они могут получить, это объединить «посты» и «комментарии», которые будут возвращать много ненужного дублирования данных (с повторением одной и той же информации поста). в каждой строке), что означает, что время обработки тратится как на базу данных, чтобы собрать все это вместе, так и на мой ORM, чтобы проанализировать и отменить все это.
Даже если я проинструктирую свой ORM с нетерпением загружать комментарии к записи, лучшее, что она сделает, - отправит один запрос к сообщению, а затем второй запрос, чтобы получить все комментарии, а затем соединит их вместе на стороне клиента, что тоже неэффективно.
Я понимаю, что реляционные базы данных являются проверенной технологией (черт, они старше меня), и что за эти десятилетия в них было проведено множество исследований, и я уверен, что есть действительно веская причина, почему они (и Стандарт SQL) предназначены для того, чтобы функционировать так, как они, но я не уверен, почему описанный выше подход невозможен. Мне кажется, это самый простой и очевидный способ реализации одного из самых основных отношений между записями. Почему реляционные базы данных не предлагают что-то подобное?
(Отказ от ответственности: я в основном пишу веб-приложения с использованием хранилищ данных Rails и NoSQL, но недавно я пробовал Postgres, и мне это очень нравится. Я не хочу атаковать реляционные базы данных, я просто озадачен.)
Я не спрашиваю, как оптимизировать приложение Rails или как обойти эту проблему в конкретной базе данных. Я спрашиваю, почему стандарт SQL работает таким образом, когда он кажется мне нелогичным и расточительным. Должна быть какая-то историческая причина, по которой первоначальные разработчики SQL хотели, чтобы их результаты выглядели так.
Ответы:
CJ Date подробно рассказывает об этом в главе 7 и приложении B к SQL и реляционной теории . Вы правы, в реляционной теории нет ничего, что запрещало бы типу данных атрибута быть самим отношением, если только он имеет одинаковый тип отношения в каждой строке. Ваш пример будет соответствовать.
Но Дэйт говорит, что подобные структуры «обычно - но не всегда - противопоказаны» (т.е. плохая идея), потому что иерархии отношений асимметричны . Например, преобразование из вложенной структуры в привычную «плоскую» структуру не всегда можно отменить, чтобы воссоздать вложение.
Запросы, ограничения и обновления являются более сложными, сложными для написания и более сложными для поддержки СУБД, если вы разрешите атрибуты со значениями отношений (RVA).
Это также запутывает принципы проектирования баз данных, потому что лучшая иерархия отношений не так ясна. Должны ли мы разработать отношение поставщиков с вложенным RVA для деталей, поставляемых данным поставщиком? Или отношение частей с вложенным RVA для поставщиков, которые поставляют данную деталь? Или хранить оба, чтобы облегчить выполнение различных типов запросов?
Это та же самая дилемма, которая возникает из иерархической базы данных и моделей баз данных, ориентированных на документы . В конечном итоге, сложность и стоимость доступа к вложенным структурам данных заставляют дизайнеров избыточно хранить данные для более удобного поиска по различным запросам. Реляционная модель препятствует избыточности, поэтому RVA могут работать против целей реляционного моделирования.
Из того, что я понимаю (я не использовал их), Rel и Dataphor являются проектами СУБД, которые поддерживают атрибуты, имеющие отношение к значениям.
Re комментарий от @dportas:
Структурированные типы являются частью SQL-99, и Oracle поддерживает их. Но они не хранят несколько кортежей во вложенной таблице на строку базовой таблицы. Типичным примером является атрибут «адрес», который выглядит как один столбец базовой таблицы, но имеет дополнительные подколонки для улицы, города, почтового индекса и т. Д.
Вложенные таблицы также поддерживаются Oracle, и они допускают несколько кортежей на строку базовой таблицы. Но я не знаю, что это является частью стандартного SQL. И имейте в виду вывод одного блога: «Я никогда не буду использовать вложенную таблицу в выражении CREATE TABLE. Вы тратите все свое время, НЕ ВСТАВЛЯЯ их, чтобы снова сделать их полезными!»
источник
x
может иметь значение целого числа 42). Те же самые операции применяются к отношениям и relvars, поэтому их структура должна быть совместимой.Некоторые из самых ранних систем баз данных были основаны на модели иерархической базы данных . Эти данные представлены в виде древовидной структуры с родителями и детьми, так же, как вы предлагаете здесь. HDMS были в значительной степени заменены базами данных, построенными на реляционной модели. Основными причинами этого было то, что RDBMS могла моделировать отношения «многие ко многим», которые были трудны для иерархических баз данных, и что RDBMS могла легко выполнять запросы, которые не были частью первоначального проекта, тогда как HDBMS ограничивала вас запросом по путям, указанным во время разработки.
Есть все еще некоторые примеры иерархических систем баз данных в дикой природе, особенно реестр Windows и LDAP.
Обширное освещение этой темы доступно в следующей статье
источник
Я полагаю, что ваш вопрос действительно связан с тем фактом, что, хотя базы данных основаны на твердой логике и устанавливают теоретические основы, они отлично справляются с хранением, манипулированием и извлечением данных в (2-мерных) наборах, обеспечивая при этом ссылочную целостность, параллелизм и многие другие, они не предоставляют (дополнительную) функцию отправки (и получения) данных в том, что можно назвать объектно-ориентированным форматом или иерархическим форматом.
Затем вы утверждаете, что «даже если я проинструктирую свой ORM с нетерпением загружать комментарии к записи, лучшее, что она сделает, - отправит один запрос к сообщению, а затем второй запрос, чтобы получить все комментарии, а затем соединить их вместе. на стороне клиента, что тоже неэффективно " .
Я не вижу ничего неэффективного в отправке 2 запросов и получении 2 пакетов результатов с:
Я бы сказал, что это (почти) наиболее эффективный способ (почти, поскольку вам не нужны
posts.id
столбцы, а не всеcomments.*
)Как указал Тодд в своем комментарии, вы не должны просить базу данных вернуть данные, готовые для отображения. Это работа приложения, чтобы сделать это. Вы можете написать (один или несколько) запросов, чтобы получить результаты, необходимые для каждой операции отображения, чтобы избежать ненужного дублирования данных, передаваемых по проводам (или шине памяти) из БД в приложение.
Я не могу говорить об ORM, но, возможно, некоторые из них могут сделать часть этой работы для нас.
Подобные методы могут использоваться при доставке данных между веб-сервером и клиентом. Используются другие методы (например, кэширование), чтобы база данных (или веб-сервер или другой сервер) не была перегружена дублирующимися запросами.
Я предполагаю, что стандарты, такие как SQL, лучше всего, если они остаются специализированными в одной области и не пытаются охватить все области поля.
С другой стороны, комитет, который устанавливает стандарт SQL, вполне может думать иначе в будущем и обеспечить стандартизацию для такой дополнительной функции. Но это не то, что можно создать за одну ночь.
источник
Я не могу ответить правильным, аргументированным ответом, поэтому не стесняйтесь переводить меня в забвение, если я ошибаюсь (но, пожалуйста, исправьте меня, чтобы мы могли узнать что-то новое). Я думаю, что причина в том, что реляционные базы данных сосредоточены на реляционной модели, которая, в свою очередь, основана на чем-то, о чем я ничего не знаю, под названием «логика первого порядка». То, что вы можете спросить, вероятно, не вписывается в математическую / логическую структуру, на которой построены реляционные базы данных. Более того, то, что вы спрашиваете, обычно легко решается с помощью графовых баз данных, давая больше подсказок, что именно базовая концептуализация базы данных конфликтует с тем, чего вы хотите достичь.
источник
Я знаю, что по крайней мере SQLServer поддерживает вложенные запросы при использовании FOR XML.
Проблема здесь не в отсутствии поддержки со стороны СУРБД, а в отсутствии поддержки вложенных таблиц в таблицах.
Кроме того, что мешает вам использовать внутреннее соединение?
Фактически вы можете посмотреть на внутреннее объединение как на вложенную таблицу, только содержимое первых 2 полей может быть повторено в любое время. Я не стал бы сильно беспокоиться о производительности объединения, единственная медленная часть в запросе, подобном этому, - это ввод данных из базы данных в клиент. Это будет проблемой, только если контент содержит большой объем данных. В этом случае я бы предложил два запроса, один с
select id, content
и один с внутренним соединением иselect posts.id, comments.*
. Это масштабируется даже с несколькими постами, так как вы все равно будете использовать только 2 запроса.источник
for xml
.На самом деле Oracle поддерживает то, что вы хотите, но вам нужно заключить в подзапрос ключевое слово «cursor». Результаты выбираются через открытый курсор. Например, в Java комментарии будут отображаться как наборы результатов. Подробнее об этом см. Документацию Oracle "CURSOR Expression"
источник
Некоторые поддерживают вложение (иерархическое).
Если вам нужен один запрос, вы можете иметь одну таблицу, которая сама ссылается на себя. Некоторые RDMS поддерживают эту концепцию. Например, в SQL Server можно использовать общие табличные выражения (CTE) для иерархического запроса.
В вашем случае сообщения будут на уровне 0, а затем все комментарии будут на уровне 1.
Другими вариантами являются 2 запроса или соединение с некоторой дополнительной информацией для каждой возвращенной записи (которую упоминали другие).
Пример иерархического:
https://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example
В приведенной выше ссылке EmpLevel показывает уровень вложенности (или иерархию).
источник
Извините, я не уверен, что точно понимаю вашу проблему.
В MSSQL вы можете просто выполнить 2 оператора SQL.
И он вернет ваши 2 набора результатов одновременно.
источник
RDBMs основаны на теории, и они придерживаются теории. Это обеспечивает хорошую согласованность и математически доказанную надежность.
Поскольку модель проста и опять-таки основана на теории, она позволяет людям легко оптимизировать и реализовать много реализаций. Это не похоже на NoSQL, где все делают это по-своему.
В прошлом предпринимались попытки создать иерархические базы данных, но у IIRC (похоже, нет, Google) возникли проблемы (на ум приходят циклы и равенство).
источник
У вас есть конкретные потребности. Было бы предпочтительнее извлекать данные из базы данных в нужном вам формате, поэтому вы можете делать с ними все, что захотите.
С некоторыми базами данных дела обстоят не так хорошо, но в любом случае невозможно создать их для этого. Оставлять форматирование для других приложений является текущей рекомендацией, но не оправдывает, почему это невозможно сделать.
Единственный аргумент, который я имею против вашего предложения - это возможность обработать этот набор результатов "sql" способом. Было бы плохой идеей создать результат в базе данных, если он не сможет работать с ним или манипулировать им до некоторой степени. Допустим, я создал представление, построенное так, как вы предлагаете, как мне включить его в другой оператор выбора? Базы данных любят получать результаты и делать что-то с ними. Как бы я присоединить его к другому столу? Как бы я сравнил ваш результат с другим?
Тогда выгода RDMS's - гибкость sql. Синтаксис для выбора данных из таблицы довольно близок к списку пользователей или других объектов в системе (по крайней мере, это цель). Не уверен, что есть смысл делать что-то совершенно другое. Они даже не довели их до такой степени, что обрабатывали процедурный код / курсоры или BLOBS данных очень эффективно.
источник
На мой взгляд, это в основном из-за SQL и способа выполнения агрегатных запросов - агрегатные функции и группировка выполняются на больших двумерных наборах строк для возврата результатов. Так было с самого начала и очень быстро (большинство решений NoSQL довольно медленно работают с агрегацией и полагаются на денормализованную схему вместо сложных запросов)
Конечно, PostgreSQL имеет некоторые особенности объектно-ориентированной базы данных. Согласно этому письму ( сообщению ) вы можете достичь того, что вам нужно, создав собственный агрегат.
Лично я использую фреймворки, такие как Doctrine ORM (PHP), которые выполняют агрегацию на стороне приложения и поддерживают такие функции, как ленивая загрузка, для повышения производительности.
источник
PostgreSQL поддерживает различные структурированные типы данных, включая массивы и JSON . Используя SQL или один из встроенных процедурных языков, вы можете создавать значения с произвольно сложной структурой и возвращать их в ваше приложение. Вы также можете создавать таблицы со столбцами любого из структурированных типов, хотя вы должны тщательно продумать, не излишне ли вы денормализуете свой дизайн.
источник