Pregunta

Tengo algunos procedimientos almacenados complejos que pueden devolver muchos miles de filas y tardan mucho tiempo en completarse.

¿Hay alguna forma de averiguar cuántas filas se devolverán antes de que la consulta se ejecute y recupere los datos?

Esto es con Visual Studio 2005, una aplicación de Winforms y SQL Server 2005.

¿Fue útil?

Solución

Una solución a su problema podría ser volver a escribir el procedimiento almacenado para que limite el conjunto de resultados a algún número, como:

SELECT TOP 1000 * FROM tblWHATEVER

en SQL Server, o

SELECT * FROM tblWHATEVER WHERE ROWNUM <= 1000

en Oracle. O implemente una solución de paginación para que el conjunto de resultados de cada llamada sea aceptablemente pequeño.

Otros consejos

Usted mencionó que sus procedimientos almacenados tardan mucho tiempo en completarse. ¿Se toma la mayor parte del tiempo durante el proceso de seleccionar las filas de la base de datos o devolver las filas a la persona que llama?

Si es lo último, quizás pueda crear una versión de réplica de su SP que solo obtenga el recuento en lugar de las filas reales. Si es lo primero, bueno, no hay mucho que puedas hacer ya que es lento encontrar las filas elegibles.

haga un proceso almacenado para contar primero las filas.

SELECCIONAR CUENTA (*) DE la tabla

A menos que haya algún aspecto de la lógica empresarial de su aplicación que permita calcular esto, no. La base de datos tendrá que hacer todo el & amp; únase a la lógica para descubrir cómo se alinean las filas, y esa es la mayor parte del tiempo que pasa en el SP.

No puede obtener el número de filas de un procedimiento sin ejecutar el procedimiento.

Podría hacer un procedimiento diferente que acepte los mismos parámetros, cuyo propósito es decirle cuántas filas debe devolver el otro procedimiento. Sin embargo, los pasos requeridos por este procedimiento normalmente serían tan similares a los del procedimiento principal que debería tomar el tiempo necesario para ejecutar el procedimiento principal.

Tendría que escribir una versión diferente del procedimiento almacenado para obtener un recuento de filas. Probablemente este sea mucho más rápido porque podría eliminar la unión de tablas con las que no se filtra, eliminar el pedido, etc. Por ejemplo, si su proceso almacenado ejecutó el sql como:

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

tu versión de conteo sería algo así como:

select count(*) from productorder where orderdate>@orderdate;

No en general.

A través del conocimiento sobre el funcionamiento del procedimiento almacenado, puede obtener una estimación o un recuento exacto (por ejemplo, si la tabla básica o básica de la consulta puede ser rápida). calculado, pero son combinaciones complejas y / o resúmenes que impulsan el tiempo hacia arriba).

Pero primero tendría que llamar al SP de conteo y luego al SP de datos o podría mirar usando un SP de conjunto de resultados múltiple.

Puede llevar tanto tiempo obtener una cuenta consecutiva como obtener los datos reales, por lo que no recomendaría realizar una cuenta en la mayoría de los casos.

Algunas posibilidades:

1) ¿SQL Server expone sus resultados del optimizador de consultas de alguna manera? es decir, ¿puede analizar la consulta y luego obtener una estimación del recuento de filas? (No sé SQL Server).

2) Tal vez, según los criterios que el usuario le dé, puede realizar algunas estimaciones propias. Por ejemplo, si el usuario ingresa 'S%' en el campo del apellido del cliente para consultar los pedidos, puede determinar que coincida con el 7% (por ejemplo) de los registros del cliente, y extrapolar que la consulta puede devolver aproximadamente 7% de los registros del pedido.

Continuando con lo que dijo Tony Andrews en su respuesta, puede obtener un plan de consulta estimado de la llamada a su consulta con:

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

Esto debería devolver una tabla, o muchas tablas que le permitirán obtener el número estimado de filas de su consulta.

Es necesario analizar el conjunto de datos devueltos, para determinar qué es una clave primaria lógica (significativa) para el conjunto de resultados que se devuelve. En general, esto SERÁ mucho más rápido que el procedimiento completo, ya que el servidor no está construyendo un conjunto de resultados a partir de los datos en todas las columnas de cada fila de cada tabla, simplemente está contando las filas ... En general, puede que ni siquiera es necesario que lea las filas de la tabla real fuera del disco para hacer esto, simplemente deberá contar los nodos de índice ...

Luego escriba otra declaración SQL que solo incluya las tablas necesarias para generar esas columnas clave (Esperemos que este sea un subconjunto de las tablas en la consulta de SQL principal), y la misma cláusula where con los mismos valores de predicado de filtrado ...

Luego agregue otro parámetro opcional al proceso almacenado llamado, digamos, @CountsOnly, con un valor predeterminado de falso (0) como tal ...

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

Luego puedes llamar al mismo proceso almacenado con @CountsOnly establecido igual a 1 para obtener el recuento de registros. El código antiguo que llama al proc todavía funcionaría como solía hacerlo, ya que el valor del parámetro se establece en falso (0), si no está incluido

Es al menos técnicamente posible ejecutar un procedimiento que coloca el conjunto de resultados en una tabla temporal. Luego, puede encontrar el número de filas antes de mover los datos del servidor a la aplicación y ahorraría tener que crear el conjunto de resultados dos veces.

Pero dudo que valga la pena, a menos que crear el conjunto de resultados lleve mucho tiempo y, en ese caso, puede ser lo suficientemente grande como para que la tabla temporal sea un problema. Es casi seguro que el momento de mover la gran mesa a través de la red será muchas veces lo que se necesite para crearla.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top