¿Cuál es la mejor manera (en cuanto al rendimiento) para paginar resultados en SQL Server 2000, 2005, 2008, 2012 si también desea obtener el número total de resultados (antes de paginar)?
sql
sql-server
performance
pagination
Panagiotis Korros
fuente
fuente
Respuestas:
Obtener el número total de resultados y paginar son dos operaciones diferentes. Por el bien de este ejemplo, supongamos que la consulta que está tratando es
En este caso, determinaría el número total de resultados usando:
... lo que puede parecer ineficiente, pero en realidad es bastante eficiente, suponiendo que todos los índices, etc. estén configurados correctamente.
A continuación, para obtener resultados reales de forma paginada, la siguiente consulta sería más eficiente:
Esto devolverá las filas 1-19 de la consulta original. Lo bueno aquí, especialmente para las aplicaciones web, es que no tiene que mantener ningún estado, excepto los números de fila que se devolverán.
fuente
Finalmente, se lanzó Microsoft SQL Server 2012 , realmente me gusta su simplicidad para una paginación, no tiene que usar consultas complejas como las respondidas aquí.
Para obtener las siguientes 10 filas simplemente ejecute esta consulta:
https://docs.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql#using-offset-and-fetch-to-limit-the-rows- regresado
Puntos clave a considerar al usarlo:
ORDER BY
Es obligatorio utilizar laOFFSET ... FETCH
cláusula.OFFSET
La cláusula es obligatoria conFETCH
. No puedes usarORDER BY ... FETCH
.TOP
no se puede combinar conOFFSET
yFETCH
en la misma expresión de consulta.fuente
LISTAGG()
/GROUP_CONCAT()
.FOR XML
: stackoverflow.com/a/273330/429949FOR XML PATH ('')
. Primero, reemplaza los caracteres de control XML con códigos de entidad XML. Espero que no tiene<
,>
o&
en sus datos! Segundo,FOR XML PATH ('')
usado de esta manera es en realidad sintaxis indocumentada. Se supone que debe especificar una columna con nombre o un nombre de elemento alternativo. No hacer ninguno no está en el documento, lo que significa que el comportamiento no es confiable. En tercer lugar, cuanto más aceptamos laFOR XML PATH ('')
sintaxis rota , menos probable es que la MS realmente proporcione una función realLISTAGG() [ OVER() ]
como la han necesitado.Increíblemente, ninguna otra respuesta ha mencionado la forma más rápida de hacer paginación en todas las versiones de SQL Server. Las compensaciones pueden ser terriblemente lentas para números de página grandes, como se compara aquí . Hay una forma completamente diferente y mucho más rápida de realizar paginación en SQL. Esto a menudo se llama el "método de búsqueda" o "paginación de conjunto de claves" como se describe en esta publicación de blog aquí .
El "predicado de búsqueda"
Los valores
@previousScore
y@previousPlayerId
son los valores respectivos del último registro de la página anterior. Esto le permite buscar la página "siguiente". Si laORDER BY
dirección esASC
, simplemente use>
en su lugar.Con el método anterior, no puede saltar inmediatamente a la página 4 sin haber obtenido primero los 40 registros anteriores. Pero a menudo, no quieres saltar tan lejos de todos modos. En cambio, obtienes una consulta mucho más rápida que podría obtener datos en tiempo constante, dependiendo de tu indexación. Además, sus páginas permanecen "estables", sin importar si los datos subyacentes cambian (por ejemplo, en la página 1, mientras está en la página 4).
Esta es la mejor manera de implementar la paginación cuando la carga diferida de más datos en aplicaciones web, por ejemplo.
Tenga en cuenta que el "método de búsqueda" también se denomina paginación de conjunto de claves .
Total de registros antes de la paginación
La
COUNT(*) OVER()
función de ventana lo ayudará a contar el número de registros totales "antes de la paginación". Si está utilizando SQL Server 2000, deberá recurrir a dos consultas para elCOUNT(*)
.fuente
OFFSET .. FETCH
o conROW_NUMBER()
trucos anteriores .RowNumber
me da 10 elementos consistentes por página. [3] no funciona con cuadrículas existentes que suponenpagenumber
ypagesize
.Desde SQL Server 2012, podemos usar
OFFSET
yFETCH NEXT
Cláusula para lograr la paginación.Pruebe esto, para SQL Server:
TechNet: paginación de una consulta con SQL Server
fuente
MSDN: ROW_NUMBER (Transact-SQL)
fuente
Hay una buena descripción general de las diferentes técnicas de paginación en http://www.codeproject.com/KB/aspnet/PagingLarge.aspx
He usado el método ROWCOUNT con bastante frecuencia principalmente con SQL Server 2000 (también funcionará con 2005 y 2008, solo mida el rendimiento en comparación con ROW_NUMBER), es muy rápido, pero debe asegurarse de que las columnas ordenadas tengan (principalmente ) valores únicos.
fuente
Para SQL Server 2000, puede simular ROW_NUMBER () utilizando una variable de tabla con una columna IDENTITY:
Este enfoque puede extenderse a tablas con claves de varias columnas, y no incurre en la sobrecarga de rendimiento del uso de OR (que omite el uso del índice). La desventaja es la cantidad de espacio temporal utilizado si el conjunto de datos es muy grande y uno está cerca de la última página. No probé el rendimiento del cursor en ese caso, pero podría ser mejor.
Tenga en cuenta que este enfoque podría optimizarse para la primera página de datos. Además, se usó ROWCOUNT ya que TOP no acepta una variable en SQL Server 2000.
fuente
La mejor forma de paginación en SQL Server 2012 es mediante el uso de desplazamiento y recuperación a continuación en un procedimiento almacenado. Palabra clave OFFSET : si usamos offset con la cláusula order by, la consulta omitirá el número de registros que especificamos en OFFSET n Filas.
FETCH NEXT Palabras clave : cuando usamos Fetch Next con una orden por cláusula, solo devolverá el número de filas que desea mostrar en la paginación, sin Offset, SQL generará un error. Aquí está el ejemplo dado a continuación.
puedes ejecutarlo de la siguiente manera.
fuente
Estas son mis soluciones para paginar el resultado de la consulta en el lado del servidor SQL. estos enfoques son diferentes entre SQL Server 2008 y 2012. Además, he agregado el concepto de filtrado y orden por con una columna. Es muy eficiente cuando busca, filtra y ordena en su Gridview.
Antes de realizar la prueba, debe crear una tabla de muestra e insertar alguna fila en esta tabla: (en el mundo real, debe cambiar la cláusula Where considerando los campos de su tabla y tal vez tenga alguna unión y subconsulta en la parte principal de select)
En todos estos ejemplos, quiero consultar 200 filas por página y estoy buscando la fila para el número de página 1200.
En SQL Server 2008, puede usar el concepto CTE. Por eso, he escrito dos tipos de consulta para SQL Server 2008+
- SQL Server 2008+
Y segunda solución con CTE en SQL Server 2008+
- SQL Server 2012+
fuente
Prueba este enfoque:
fuente
En el caso de uso, lo siguiente parece ser fácil de usar y rápido. Simplemente configure el número de página.
también sin CTE
fuente
Bueno, he usado la siguiente consulta de muestra en mi base de datos SQL 2000, también funciona bien para SQL 2005. El poder que le da está ordenado dinámicamente mediante el uso de múltiples columnas. Te digo ... esto es poderoso :)
La mejor parte es que sp_executesql almacena en caché las llamadas posteriores, siempre que pase los mismos parámetros, es decir, genere el mismo texto sql.
fuente
reiniciará idx cuando se trata de init_id diferente
fuente
Para la
ROW_NUMBER
técnica, si no tiene una columna de clasificación para usar, puede usar loCURRENT_TIMESTAMP
siguiente:Esto me ha funcionado bien para búsquedas en tamaños de tabla de hasta 700,000.
Esto obtiene registros de 11 a 30.
fuente
fuente
Este bit le brinda la capacidad de paginar usando SQL Server y las versiones más recientes de MySQL y lleva el número total de filas en cada fila. Utiliza tu clave de pimary para contar el número de filas únicas.
fuente
Este es un duplicado de la antigua pregunta SO 2012: forma eficiente de implementar la paginación
Aquí el tema se discute con mayor detalle y con enfoques alternativos.
fuente
A partir de 2012 podemos usar
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
fuente
No especificó el idioma ni qué controlador está utilizando. Por lo tanto, lo estoy describiendo de manera abstracta.
fuente