2010-01-06 11 views
6

Estoy trabajando en devolver un conjunto de registros de SQL Server 2008 para hacer algunas paginación. Solo estoy devolviendo 15 registros a la vez, pero necesito tener el número total de coincidencias junto con el subconjunto de registros. He usado dos consultas diferentes con resultados mixtos, dependiendo de en qué parte del grupo más grande necesito extraer el subconjunto. He aquí una muestra:Obtener un subconjunto de registros junto con el recuento total de registros

SET NOCOUNT ON; 
WITH tempTable AS (
    SELECT 
    FirstName 
    , LastName 
    , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
    FROM People 
    WHERE 
     Active = 1 
) 

SELECT 
    tempTable.*  
    , (SELECT Max(RowNumber) FROM tempTable) AS Records  
FROM tempTable  
WHERE 
    RowNumber >= 1 
    AND RowNumber <= 15 
ORDER BY 
    FirstName 

Esta consulta funciona realmente rápido cuando estoy devolución de artículos en el extremo inferior de partidos, como registros de 1 a 15. Sin embargo, cuando empiece a devolver los registros de 1000 a 1015, el procesamiento pasará de menos de un segundo a más de 15 segundos.

Así que cambió la consulta a la siguiente en su lugar:

SET NOCOUNT ON; 
WITH tempTable AS (
    SELECT * FROM (
    SELECT 
     FirstName 
     , LastName 
     , ROW_NUMBER() OVER(ORDER BY FirstName ASC) AS RowNumber 
     , COUNT(*) OVER(PARTITION BY NULL) AS Records 
     FROM People 
     WHERE 
     Active = 1 
    ) derived 
    WHERE RowNumber >= 1 AND RowNumber <= 15 
) 

SELECT 
    tempTable.*  
FROM tempTable  
ORDER BY 
    FirstName 

Esa consulta se ejecuta el número de altos rendimientos en 2-3 segundos, sino que también ejecuta las consultas de números bajos en 2-3 segundos también. Debido a que realiza el recuento de cada una de las más de 70,000 filas, hace que cada solicitud de tome más tiempo en lugar de solo los números de fila grandes.

Así que tengo que averiguar cómo obtener un buen recuento de filas, así como solo devolver un subconjunto de elementos en cualquier punto del conjunto de resultados sin sufrir una penalización tan grande. Podría manejar una penalización de 2-3 segundos para los números altos de la fila, pero 15 es demasiado, y no estoy dispuesto a sufrir cargas lentas en las primeras páginas que ve una persona.

NOTA: Sé que no necesito el CTE en el segundo ejemplo, pero esto es solo un ejemplo simple. En producción, estoy haciendo más uniones en la tabla de temptables una vez que la haya filtrado a las 15 filas que necesito.

+0

Véase también [esto] (http://www.sqlservercentral.com/articles/paging/70120 /). –

Respuesta

8

Aquí es lo que he hecho (y su igual de rápido, no importa que registra vuelvo):

--Parameters include: 
@pageNum int = 1, 
@pageSize int = 0, 



DECLARE 
    @pageStart int, 
    @pageEnd int 

SELECT 
    @pageStart = @pageSize * @pageNum - (@pageSize - 1), 
    @pageEnd = @pageSize * @pageNum; 


SET NOCOUNT ON; 
WITH tempTable AS (
    SELECT 
     ROW_NUMBER() OVER (ORDER BY FirstName ASC) AS RowNumber, 
     FirstName 
     , LastName 
    FROM People 
    WHERE Active = 1 
) 

SELECT 
    (SELECT COUNT(*) FROM tempTable) AS TotalRows, 
    * 
FROM tempTable 
WHERE @pageEnd = 0 
OR RowNumber BETWEEN @pageStart AND @pageEnd 
ORDER BY RowNumber 
+0

Bastante seguro de que este es el problema aquí. 'RowNumber' es una columna derivada y, por lo tanto, no indexada, mientras que' COUNT (*) 'puede usar el índice. +1. – Aaronaught

+0

Lo has conseguido ... el proceso pasó de 15-20 segundos a menos de 1. Gracias :-) –

0

He manejado una situación parecida a esta en el pasado al no molestarme en determinar un conteo de filas definido, pero usando el plan de consulta para darme un recuento de filas estimado, un poco como el primer elemento en este enlace describe:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=108658

la intención era entonces para entregar lo filas se han solicitado dentro del rango (de por ejemplo 900 a 915) y luego devolver el número de filas estimado, como

rows 900-915 of approx. 990 

cuales evitado tener contar todas las filas Una vez que el usuario se mueve más allá de ese punto, me acaba de aparecer

rows 1000-1015 of approx. 1015 

es decir, limitarse a tomar la última fila solicitada como mi nueva estimación.

+0

Desafortunadamente eso no tomará en cuenta los criterios de búsqueda. –

Cuestiones relacionadas