powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Эффективнось запуска SP из ADO
18 сообщений из 18, страница 1 из 1
Эффективнось запуска SP из ADO
    #32015520
olegusan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Коллеги,
Какой способ запуска Stored Procedure из ADO более эффективный и почему?

1.
Cmd.ActiveConnection = cn
Cmd.CommandType = adCmdStoredProc
Cmd.CommandText = "my_cool_sp"
Set rs = Cmd.Execute

2.
Set Rs = Server.CreateObject("ADODB.Recordset")
Set Rs.ActiveConnection = cn
Rs.CursorType = adOpenStatic
Rs.LockType = adLockReadOnly
Rs.Source = "exec my_cool_sp"
Rs.Open
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015527
Фотография tygra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Чего-то мне кажется, что все одинаково, только с помощью второго способа можно только рекордсет получить из процедуры, и то если в ней ничего ни куда не вставляется, а с помощью первого метода можно все что хочешь сделать, хоть параметры обратно получать.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015528
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
Правильнее поставить вопрос, в чем различие между такими вариантами:
1. Cmd.ActiveConnection = cn
Cmd.CommandType = adCmdStoredProc
Cmd.CommandText = "my_cool_sp"
Set rs = Cmd.Execute

2. Cmd.ActiveConnection = cn
Cmd.CommandType = adCmdText
Cmd.CommandText = "exec my_cool_sp"
Set rs = Cmd.Execute

Твой второй вариант в дебрях ADO выполняет примерно то, что было бы выполнено по приведенному мной варианту 2. Задействуются одни и те же механизмы, только через разные двери. А вот разница между приведенными мной вариантами действительно есть, и она недавно была выявлена моим коллегой при работе с типами sql_variant MS SQL SERVER 2000. Если хранимая процедура использует параметры типа sql_variant, через который на сервер передается текстовая информация, то во втором варианте эта информация получае colation, назначенный как default colation для сервера и базы данных, а в первом случае colation силком проставляется внутренними механизмами ADO, который чаще всего не совпадает с collation всей остальной используемой в БД текстовой информации. Не совпадение collation при сравнении двух значений типа sql_variant приводит к невыполнению равенства, хотя текст содержит одну и ту же фразу (да еще на английском). Нам пришлось все вызовы первого типа заменить на вызовы второго типа, чтобы устранить проблемы с collation. Следует оговориться, что данные проблемы возникают ТОЛЬКО при использовании вариантных параметров. Для всех других типов параметров они не возникают.

А насчет эффективности - IMHO те же шары, только в профиль. Возможно, имеются какая-то разница в скорости выполнения первого и второго кода, но обычно такой код не включают в в тело самого глубокого из пяти вложенных циклов, поэтому в основном эта разница значения существенной роли не играет.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015529
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
2 tygra
Откуда такая информация, что по первому способу нельзя вызвать процедуру, если в ней что-то куда-то вставляется? Кроме оговоренной проблемы с Collation IMHO между ними вообще нет разницы.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015530
Фотография tygra
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
To Garya

По второму, а не по первому.
Может конечно чего недонастроил, но пробовал всяко:
из ASP когда открываешь процедуру, в которой select ...... и все, то все нормально, а если в ней куда-то есть insert ...., то обломись.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015548
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
А в чем этот обломись заключается? Какое выводится сообщение об ошибке? Не "облом-с!" же?
Наугад можно предположить, что проблемы могли возникнуть с правами доступа. Проблемы действительно могли возникнуть, если в хранимой процедуре используется динамический SQL. Часть запроса, которая сформировалась динамически, запускается в отдельном контенте и не с правами владельца хранимой процедуры, а с правами пользователя, который может не иметь достаточных прав для доступа к соответствующим таблицам напрямую. Больше с ходу ничего в голову не приходит.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015555
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Товарищи! Используйте всегда вариант 2. Он быстрее (а не как вы подумали) и надёжнее.
Я встречался с такой ошибкой: в VB коннекшн перестаёт работать, пока не уничтожить последний объект ADODB.Command...
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015607
olegusan
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем спасибо за ответы!
Я тоже думаю, что никакой разницы нет.
Просто у нас на работе спор возник. Мы взяли на работу нового программиста, а он утверждает, что второй вариант вызывает перекомпиляцию процедуры при вызове. Принародно убеждать его я не стал, - на испытательном сроке человек.
Но сам на всякий случай засомневался.

Еще раз спасибо.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015850
AnatolyS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Давно не брал я в руки шашки...
Помнится, что вариант с Cmd.CommandType = adCmdStoredProc
приводит к дополнительному запросу к серверу от ADO
с целью получить метаданные - всякие там параметры процедурные...
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015876
Павел
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
2 AnatolyS

Да, давненько Вы шашку не брали...
Коллекеция параметров заполняется методоим .Refresh. Если тип команды - текст, то можно аказать/отказаться от его размещения в процедурном кэше свойством .Prepared.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015910
George
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Никогда!! не пользуйтесь методом 2.
Только #1.
Второй вариант вызывает перекомпиляцию пакета " exec my_cool_sp". Вы ведь спокойно могли написать "begin tran
if ... begin ... end commit tran" или чего еще. Цитата из BOL "The prepared statement adds a small precompiled execution plan that calls the stored procedure execution plan, rather than executing the stored procedure execution plan directly."

Во-вторых второй! а не первый вариант приводит к рефрешу параметров только на внутреннем уровне SQL Server. Как часть компиляции пакета.
В-третьих производится двойное приведение типов: сначала на клиенте в строку, затем при разборе пакета обратно в тип параметров.
В-четвертых вы теряете возможность получать out-параметры кроме как в рекордсете. Но рекордсет гораздо более ресурсоемкий объект, чем параметр (см. документацию к OLEDB).

Ну и, наконец, не дай бог, пропустить кавычку или апостроф или столкнуться с разными LCID при составлении скрипта вызова SP.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015979
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемый George!
Позволю с Вмаи не согласиться.
П. 1. Действительно, #2 вызывает перекомпиляцию пакета " exec my_cool_sp". Однако время перекомпиляции столь мало, что его нельзя измерить. Несколько лет назад мы проводили тесты (я доказывал своему начальнику, что выриант #1 быстрее
), и быстрее оказался #2...

П. 2. Под рефрешем параметров подразумевается запрос клиентом параметров процедуры у сервера. Первый вариант может приводить к рефрешу параметров при использовании метода рефреш. Второй вариант не может приводить к рефрешу параметров, т.к. их нет. "приводит к рефрешу параметров только на внутреннем уровне SQL Server" - это не рефреш, это компиляция стейтмента.

П. 3. Это всё та-же компиляция стейтмента!!! Очень быстрая.

П. 4. "рекордсет гораздо более ресурсоемкий объект" - это зависит от стиля написания и используемого окружения. Использовать нужно не RS("MyField"), а метод GetRows. При этом:
П. 4а. ASP - рекордсет быстрее в десятки раз. Не забывайте, что использование Cmd.Parameters(...) - это обращение к ОЛЕ, поиск метода по имени(!!!), маршаллинг и т.д. - сотни тысяч команд процессора. Кроме того, для работы с #1 придётся вызывать десятки методов через ОЛЕ, а в #2 - только 3:
set rs = conn.Execute(...)
vArray = rs.GetRows()
rs.Close
И всё! Серверные ресурсы освобождены - можно работать с данными - причём быстро.
П. 4б. Компилируемый язык - рекордсет медленнее при малом к-ве полей, и такой-же - при большом.

П. 5. Главное преимущество #2 - меньше потенциальных ошибок, в частности потому, что всю работу с АДО можно вынести в отдельный модуль с 3-мя функциями. Простой пример - разработчикам пришла мысль, что хорошо-бы при сообщении о дедлоке повторять запрос. При методе 1 - переписывать приложение. При методе 2 - переписать одну функцию.

Могу Вас уверить, что на своём и чужом опыте многократно убеждался использование первого метода ведёт к замедлению работы и уменьшению стабильности системы.

С уважением, Алексей.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32015995
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не понимаю зачем копья ломать, когда можно в Trace посмотреть что делается.
На самом деле в обоих случаях выполняется строчка "exec my_cool_sp". И именно эта строчка и будет компилироваться. С какой стати будет перекомпилироваться вся процедура?
Во втором случае добавиться еще select для возвращаемых параметров и кода возврата. Предварительное чтение метаданных тоже будет, но только один раз - при следующем вызове процедуры их уже незачем читать. К тому же занимает это мгновение.

2 alexeyvg

Не забывайте, что использование Cmd.Parameters(...) - это обращение к ОЛЕ, поиск метода по имени(!!!), маршаллинг и т.д. - сотни тысяч команд процессора.
Бедный процессор, аж жалко стало. Ну посчитайте за сколько 100MHz процессор выполнит сто тысяч команд. А если еще учесть что он некоторые команды выполняет параллельно, по 2 за такт...
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32016012
Фотография alexeyvg
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2SergSuper
>Бедный процессор...
Между прочим, это замедление существенно, оно заметно "на глаз". Сейчас не принято оптимизировать программы, а зря. Время выполнения плохо написанной АСП-страницы может дойти и до десятых долей секунды. Даже при небольшой нагрузке такое приложение загаживает целиком весь сервер.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32016073
George
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
> П. 3. Это всё та-же компиляция стейтмента!!! Очень быстрая.
Конечно, компиляция стейтмента. Тут все есть компиляция стейтмента.

Тут речь не о скорости выполнения пакета, т.к. ее действительно "нельзя измерить".А об уменьшении трудозатрат. Приходится больше программировать клиентскую часть.

> Использовать нужно не RS("MyField"), а метод GetRows.
Это кому как нравится. Метод GetRows вообще имеет массу недостатков. Копирование рекордсета в массив - на любителя.

> Главное преимущество #2 - меньше потенциальных ошибок, в частности потому, что всю работу с АДО можно вынести в отдельный модуль с 3-мя функциями.
Да - 3 функции это круто. Интересно, а зачем тогда в ADO их гораздо больше? Ведь достаточно только Connection.Execute(), а?
Потенциальных ошибок не меньше - гораздо больше. И именно с приведениями типов при разных LCID клиента и сервера.

>Между прочим, это замедление существенно, оно заметно "на глаз". Сейчас не принято оптимизировать программы, а зря. Время выполнения плохо написанной АСП-страницы может дойти и до десятых долей секунды.

Если замедление вызывает создание пераметров, то АСП не просто полохо, а очень плохо написан. Например, если специально плохо написан.

> Не забывайте, что использование Cmd.Parameters(...) - это обращение к ОЛЕ, поиск метода по имени(!!!), маршаллинг и т.д. - сотни тысяч команд процессора.

Маршаллинг и IDispatch используется в любом случае, если работа идет из ASP. Если же работа идет из C++, то это как напишешь.
Однако вызов SP методами объекта Command приводит к прямому RPC вызову нужной процедуры.
Тогда как вызов SP методами объекта Recordset вызывает процедуру прекомпиляции пакета.

Вообще, у Microsoft сказано:
Don't return a rowset unless you must. ADO constructs a Recordset object whenever the query being executed returns rows. Recordset objects are expensive to construct, so avoid them whenever possible. After it's built, the Recordset provides powerful features, and if you find them useful, you can use a Recordset to pass data back from SQL Server. Keep in mind that it's possible to execute queries that return results but no rows. For example, you can return integer values by using the Return Status parameter. Also, you can return up to 1000 Output parameters (from SQL Server) instead of a rowset, which would require construction of a Recordset.

Я думаю, что дискуссия безсмысленна. Каждый останется при своем мнении.
Раньше я видел, написано было в BOL, что вызов хранимки методом Command является наиболее эффективным, но сейчас найти этой строчки не могу. Однако нигде в литературе вы не найдете строки, подтверждающей эффективность пункта 2.
Везде при вызове SP используется Command de-facto. Иногда Connection (если out-параметров нет).
Я какое-то время назад исследовал проблему вызова SP из ASP страниц. Сидел и с профайлером и груду лит-ры перечитал. Даже перехватывал RPC пакеты. Нашел груду неописанного MS поведения (например, для MS SQL 7.0 невозможно использовать Default-значения для out параметров).

На мой взгляд, методы объекта Recordset нужно вообще использовать как можно реже.
А рекомендаций по использованию разных ADO объектов в MSDN предостаточно.
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32016094
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
>В-четвертых вы теряете возможность получать out-параметры кроме как в рекордсете. Но рекордсет гораздо более ресурсоемкий объект, чем параметр (см. документацию к OLEDB).

Вовсе мы ничего не теряем.
Cmd.CommandText = "exec MyProc ?, ? ? output"
Далее при создании коллекции параметров (это необходимо сделать самому) при создании третьего параметра необходимо указать direction=InputOutput
И все! У меня работает.
Кстати, при создании на клиенте "врукопашную" параметров (без метода Refresh) по первому методу имена параметрам необходимо давать в точности такие, как они даны в описании хранимой процедуры - вместе с символом @. По второму варианту имена параметров могут быть произвольные.

И еще.
Согласен с SergSuper. То, что приходит на сервер что по первому, что по второму варианту, отличается мало. Время компиляции одной строчки из трех слов - это не та тема, которую имеет смысл обсуждать.
Лично я использую вариант 1 просто потому, что это удобнее (чуть меньше писанины), но только в тех случаях, когда речь не идет об sql_variant. Когда необходимо использовать sql_variant, альтернативы второму способу нет (см. выше).
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32016097
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
>В-четвертых вы теряете возможность получать out-параметры кроме как в рекордсете. Но рекордсет гораздо более ресурсоемкий объект, чем параметр (см. документацию к OLEDB).

Вовсе мы ничего не теряем.
Cmd.CommandText = "exec MyProc ?, ? ? output"
Далее при создании коллекции параметров (это необходимо сделать самому) при создании третьего параметра необходимо указать direction=InputOutput
И все! У меня работает.
Кстати, при создании на клиенте "врукопашную" параметров (без метода Refresh) по первому методу имена параметрам необходимо давать в точности такие, как они даны в описании хранимой процедуры - вместе с символом @. По второму варианту имена параметров могут быть произвольные.

И еще.
Согласен с SergSuper. То, что приходит на сервер что по первому, что по второму варианту, отличается мало. Время компиляции одной строчки из трех слов - это не та тема, которую имеет смысл обсуждать.
Лично я использую вариант 1 просто потому, что это удобнее (чуть меньше писанины), но только в тех случаях, когда речь не идет об sql_variant. Когда необходимо использовать sql_variant, альтернативы второму способу нет (см. выше).
...
Рейтинг: 0 / 0
Эффективнось запуска SP из ADO
    #32016098
Фотография Garya
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Garya Привилегированный пользователь
Участник
>В-четвертых вы теряете возможность получать out-параметры кроме как в рекордсете. Но рекордсет гораздо более ресурсоемкий объект, чем параметр (см. документацию к OLEDB).

Вовсе мы ничего не теряем.
Cmd.CommandText = "exec MyProc ?, ? ? output"
Далее при создании коллекции параметров (это необходимо сделать самому) при создании третьего параметра необходимо указать direction=InputOutput
И все! У меня работает.
Кстати, при создании на клиенте "врукопашную" параметров (без метода Refresh) по первому методу имена параметрам необходимо давать в точности такие, как они даны в описании хранимой процедуры - вместе с символом @. По второму варианту имена параметров могут быть произвольные.

И еще.
Согласен с SergSuper. То, что приходит на сервер что по первому, что по второму варианту, отличается мало. Время компиляции одной строчки из трех слов - это не та тема, которую имеет смысл обсуждать.
Лично я использую вариант 1 просто потому, что это удобнее (чуть меньше писанины), но только в тех случаях, когда речь не идет об sql_variant. Когда необходимо использовать sql_variant, альтернативы второму способу нет (см. выше).
...
Рейтинг: 0 / 0
18 сообщений из 18, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Эффективнось запуска SP из ADO
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]