SQL Server 2005 - есть ли серьезные отрицательные последствия для возврата нескольких таблиц с хранимыми процедурами? - PullRequest
2 голосов
/ 10 августа 2009

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

Пример:

Выберите CustomerID, CustomerEmail, CustomerAddress, InventoryLineItem, ShipQty из ...

Возвращает:

55 a@b.com 723 StreetName InvLineItem#1 45
55 a@b.com 723 StreetName InvLineItem#2 42
55 a@b.com 723 StreetName InvLineItem#3 1
55 a@b.com 723 StreetName InvLineItem#4 5
55 a@b.com 723 StreetName InvLineItem#5 200
55 a@b.com 723 StreetName InvLineItem#6 7045

(первые 3 поля никогда не меняются)

Поскольку я являюсь единственным разработчиком проекта, я начал разбивать его на два оператора select. (Я также работаю над получением кода .NET)

выберите CustomerID, CustomerEmail, CustomerAddress из ....

Returns: 55 a@b.com 723 Streetname  <-- 1 record

выберите InventoryLineItem, ShipQty из .... Возвращает:

LineItem#1 45
LineItem#2 42
LineItem#3 1

и т.д.

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

Я чувствую, что здесь все правильно, но опять же, я не профессионал по SQL.

Есть ли какие-либо причины для меня, чтобы избежать этой практики?

Заранее спасибо за ваше время.

Ответы [ 7 ]

3 голосов
/ 10 августа 2009

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

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

Так что в общем - дерзайте! :-) Для меня это отличная идея.

Марк

3 голосов
/ 10 августа 2009

Я все время использую несколько наборов результатов.

В вашем случае у меня было бы 2, один для заголовка и один для детализации. Часто клиент все равно должен извлечь заголовок: зачем мне его распрямлять (например, раздувать), если клиент не может его так использовать?

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

Скажем, одна строка заголовка, 5, строки сведений + строки поиска для раскрывающегося списка строк сведений.

Другая причина - производительность. SQL-запросы могут быть настроены, C # -код может быть настроен, но циклические обращения (например, web <-> база данных) не могут быть.

3 голосов
/ 10 августа 2009

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

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

2 голосов
/ 10 августа 2009

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

Возможно, вы вызываете хранимую процедуру с одним и тем же параметром, который вы выбираете.

например. GetCustomerOrders 'ALFKI' - который может возвращаться

АЛЬФКИ | ALFA Customer | OID001 ......
АЛЬФКИ | ALFA Customer | OID002 ......
АЛЬФКИ | ALFA Customer | OID003 ......

Таким образом, вы можете избежать ВЫБОРА поля, которое вы передаете в качестве параметра для хранимого процесса.

РЕДАКТИРОВАТЬ: Если подумать, может быть другая хранимая процедура, которая будет возвращать информацию, связанную с клиентом. Процедура, связанная со счетами, вернет данные счетов для данного идентификатора клиента.

1 голос
/ 10 августа 2009

Похоже, что это не относится к вашей ситуации, но если хранимая процедура вызывается другой хранимой процедурой, любые наборы данных, возвращаемые после первой, будут «невидимыми», то есть недоступными, процедура вызова. Трудно делать операторы INSERT ... EXECUTE .... (Конечно, эти наборы будут возвращены вызывающему приложению.)

1 голос
/ 10 августа 2009

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

1 голос
/ 10 августа 2009

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

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

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

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

Rob

...