Могу ли я получить количество строк перед выполнением хранимой процедуры? - PullRequest
5 голосов
/ 31 октября 2008

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

Есть ли способ узнать, сколько строк будет возвращено до того, как запрос будет выполнен и извлечет данные?

Это с Visual Studio 2005, приложением Winforms и SQL Server 2005.

Ответы [ 11 ]

6 голосов
/ 31 октября 2008

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

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

0 голосов
/ 31 октября 2008

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

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

0 голосов
/ 31 октября 2008

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

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

Затем добавьте еще один необязательный параметр в Stored Proc, называемый, скажем, @CountsOnly, со значением по умолчанию false (0), так что ...

Alter Procedure <storedProcName>
@param1 Type, 
-- Other current params
@CountsOnly TinyInt = 0
As
Set NoCount On

   If @CountsOnly = 1
       Select Count(*) 
       From TableA A 
          Join TableB B On   etc. etc...
       Where < here put all Filtering predicates >

   Else
      <Here put old SQL That returns complete resultset with all data>

  Return 0

Затем вы можете просто вызвать тот же хранимый процесс с @CountsOnly, установленным равным 1, чтобы просто получить количество записей. Старый код, который вызывает proc, будет по-прежнему функционировать так, как раньше, так как значение параметра по умолчанию установлено в false (0), если оно не включено

0 голосов
/ 31 октября 2008

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

SET showplan_text OFF
GO
SET showplan_all on
GO
--Replace with call you your stored procedure
select * from MyTable
GO 
SET showplan_all ofF
GO

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

0 голосов
/ 31 октября 2008

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

SELECT TOP 1000 * FROM tblWHATEVER

в SQL Server или

SELECT * FROM tblWHATEVER WHERE ROWNUM <= 1000

в Oracle. Или внедрите решение для пейджинга, чтобы набор результатов каждого вызова был приемлемо небольшим.

0 голосов
/ 31 октября 2008

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

Некоторые возможности:

1) Предоставляет ли SQL Server свои результаты оптимизации запросов каким-либо образом? то есть вы можете проанализировать запрос и затем получить оценку количества строк? (Я не знаю SQL Server).

2) Возможно, основываясь на критериях, которые дает пользователь, вы можете выполнить некоторые собственные оценки. Например, если пользователь вводит «S%» в поле фамилии клиента для запроса заказов, вы можете определить, что это соответствует 7% (скажем) записей клиентов, и экстраполировать, что запрос может вернуть около 7 % записей заказов.

0 голосов
/ 31 октября 2008

Не в общем.

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

Но вам придется сначала вызвать подсчет SP, а затем SP данных, или вы можете посмотреть, используя SP с несколькими наборами результатов.

0 голосов
/ 31 октября 2008

Вам нужно написать другую версию хранимой процедуры, чтобы получить количество строк. Это, вероятно, будет намного быстрее, потому что вы можете исключить объединение таблиц, по которым вы не фильтруетесь, удалить упорядочение и т. Д. Например, если ваш сохраненный процесс выполнил sql, например:

select firstname, lastname, email, orderdate  from 
customer inner join productorder on customer.customerid=productorder.productorderid
where orderdate>@orderdate order by lastname, firstname;

Ваша версия для подсчета будет выглядеть примерно так:

select count(*) from productorder where orderdate>@orderdate;
0 голосов
/ 31 октября 2008

Вы не можете получить количество строк процедуры без ее выполнения.

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

0 голосов
/ 31 октября 2008

Если нет какой-то стороны бизнес-логики вашего приложения, которая позволяет рассчитать это, нет. База данных должна будет выполнять всю логику where & join, чтобы выяснить, как строки строки, и это подавляющее большинство времени, проводимого в SP.

...