Каков наилучший способ обработки (вложенных) наборов записей? - PullRequest
1 голос
/ 03 апреля 2009

Каковы лучшие (более чистые, менее дорогостоящие) способы передачи отношений один-ко-многим от сервера БД к клиенту?

Представьте, что у меня есть таблица Author и таблица Book. Я хочу найти всех авторов, чье имя начинается с «а», и всех книг, которые они написали. Затем на стороне клиента создайте массив объектов «Автор», чье поле «Книги» является массивом объектов «Книги».

Мне приходят на ум два решения для бедняков:

  1. Получить всех авторов, пролистать их на клиенте и выполнить дополнительный запрос, чтобы получить все книги
  2. "ВЫБЕРИТЕ а. * ОТ автора а, книга b ГДЕ a.name вроде 'A%' и b.author_id = a.id"

Первое решение действительно интенсивно использует базу данных (если у меня 1000 авторов, мне нужно выполнить 1001 запрос).

Второе требует некоторой интенсивной работы на стороне клиента, так как программа будет анализировать результат, так как она имеет общие для Автора данные, повторяемые в каждой строке.

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

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

Есть идеи? Спасибо

EDIT: Я использую .net, так что данные ADO вариант. Они поддерживают моего оракула и MySQL?

Ответы [ 5 ]

2 голосов
/ 04 апреля 2009

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

Сначала как его собрать:

SELECT a.* FROM Author a INNER JOIN Book b ON a.id=b.author_id WHERE left(a.name,1)='a'

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

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

SELECT a.Name count(b.author_id) titles 
FROM Author a INNER JOIN Book b ON a.id=b.author_id 
WHERE left(a.name,1)='a'
GROUP BY a.Name

Они увидят

John Adam:  35 Titles
Jane Acaba: 18 Titles
Jim Allan:  3 Titles

Затем пользователь нажимает на автора, загружает список книг для этого автора.

Jim Allan's Titles:
   Froggy went a court'n
   Death on the Nile
   Life in Africa

Если вы хотите, чтобы это выглядело так, как будто все сделано одним нажатием, но вы хотите, чтобы оно появилось очень быстро, используйте xmlhttp или ajax для отображения списка авторов. Это совсем другая тема. :)

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

НТН

0 голосов
/ 03 апреля 2009

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

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

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

0 голосов
/ 03 апреля 2009

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

Например, Microsoft SQL Server, начиная с SQL 2000, поддерживает SELECT FOR XML. Это, когда схема XML тщательно разработана (например, FOR XML EXPLICIT), будет делать именно то, что вы хотите - вернуть XML, который дает вам иерархию данных. Если вы также используете ADO.NET и решите загрузить его в DataSet с помощью SqlDataAdaptor, результирующий DataSet фактически будет иметь все данные, уже установленные в DataTables, с правильными DataRelations, установленными между DataTables. Однако, это, вероятно, особенность MS-SQL, и для работы в другой СУБД могут потребоваться другие методы.

0 голосов
/ 03 апреля 2009

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

0 голосов
/ 03 апреля 2009

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

При этом вам может понадобиться создать слой между клиентом и базой данных - на компьютере базы данных - который может фильтровать и обрабатывать строки из БД в структуре (структурах) данных по вашему выбору.

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