Qual é a melhor maneira (em termos de desempenho) de paginar resultados no SQL Server 2000, 2005, 2008, 2012 se você também deseja obter o número total de resultados (antes de paginar)?
sql
sql-server
performance
pagination
Panagiotis Korros
fonte
fonte
Respostas:
Obter o número total de resultados e paginar são duas operações diferentes. Para fins de exemplo, vamos supor que a consulta com a qual você está lidando seja
Nesse caso, você determinaria o número total de resultados usando:
... o que pode parecer ineficiente, mas na verdade é bastante eficiente, assumindo que todos os índices etc. estejam configurados corretamente.
Em seguida, para obter resultados reais de volta em uma paginação, a seguinte consulta seria mais eficiente:
Isso retornará as linhas de 1 a 19 da consulta original. O legal aqui, especialmente para aplicativos da Web, é que você não precisa manter nenhum estado, exceto os números das linhas a serem retornados.
fonte
Finalmente, o Microsoft SQL Server 2012 foi lançado, eu realmente gosto de sua simplicidade para uma paginação, você não precisa usar consultas complexas como as respondidas aqui.
Para obter as próximas 10 linhas, basta executar 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- devolvida
Pontos principais a serem considerados ao usá-lo:
ORDER BY
é obrigatório usar aOFFSET ... FETCH
cláusula.OFFSET
é obrigatória comFETCH
. Você não pode usarORDER BY ... FETCH
.TOP
não pode ser combinado comOFFSET
eFETCH
na mesma expressão de consulta.fonte
LISTAGG()
/GROUP_CONCAT()
.FOR XML
: stackoverflow.com/a/273330/429949FOR XML PATH ('')
. Primeiro, ele substitui caracteres de controle XML por códigos de entidade XML. Espero que você não tem<
,>
ou&
em seus dados! Segundo,FOR XML PATH ('')
usado dessa maneira é realmente uma sintaxe não documentada. Você deve especificar uma coluna nomeada ou um nome de elemento alternativo. Não fazer nenhum deles não está no documento, o que significa que o comportamento não é confiável. Terceiro, quanto mais aceitamos aFOR XML PATH ('')
sintaxe quebrada , menos provável é que o MS realmente forneça uma função realLISTAGG() [ OVER() ]
como eles precisavam.Incrivelmente, nenhuma outra resposta mencionou a maneira mais rápida de fazer a paginação em todas as versões do SQL Server. As compensações podem ser terrivelmente lentas para números de páginas grandes, como é comparado aqui . Existe uma maneira totalmente diferente e muito mais rápida de realizar a paginação no SQL. Isso geralmente é chamado de "método de busca" ou "paginação do conjunto de teclas", conforme descrito nesta postagem do blog aqui .
O "predicado de busca"
Os valores
@previousScore
e@previousPlayerId
são os respectivos valores do último registro da página anterior. Isso permite que você busque a página "próxima". Se aORDER BY
direção forASC
, basta usar>
.Com o método acima, você não pode pular imediatamente para a página 4 sem buscar primeiro os 40 registros anteriores. Mas muitas vezes você não quer ir tão longe assim. Em vez disso, você recebe uma consulta muito mais rápida que pode buscar dados em tempo constante, dependendo da indexação. Além disso, suas páginas permanecem "estáveis", independentemente dos dados subjacentes serem alterados (por exemplo, na página 1, enquanto você estiver na página 4).
Essa é a melhor maneira de implementar a paginação ao carregar preguiçosamente mais dados em aplicativos da web, por exemplo.
Observe que o "método de busca" também é chamado de paginação do conjunto de chaves .
Total de registros antes da paginação
A
COUNT(*) OVER()
função da janela ajudará você a contar o número total de registros "antes da paginação". Se você estiver usando o SQL Server 2000, precisará recorrer a duas consultas para oCOUNT(*)
.fonte
OFFSET .. FETCH
ou comROW_NUMBER()
truques anteriores .RowNumber
me fornece 10 itens consistentes por página. [3] não funciona com grades existentes que assumempagenumber
epagesize
.A partir do SQL Server 2012, podemos usar
OFFSET
eFETCH NEXT
Cláusula para conseguir a paginação.Tente isso, para o SQL Server:
TechNet: Paginando uma consulta com o SQL Server
fonte
MSDN: ROW_NUMBER (Transact-SQL)
fonte
Há uma boa visão geral das diferentes técnicas de paginação em http://www.codeproject.com/KB/aspnet/PagingLarge.aspx
Eu usei o método ROWCOUNT frequentemente com o SQL Server 2000 (também funcionará com 2005 e 2008, apenas avalie o desempenho em comparação com ROW_NUMBER), é extremamente rápido, mas você precisa garantir que as colunas classificadas tenham (principalmente ) valores exclusivos.
fonte
Para o SQL Server 2000, você pode simular ROW_NUMBER () usando uma variável de tabela com uma coluna IDENTITY:
Essa abordagem pode ser estendida para tabelas com chaves de várias colunas e não implica em sobrecarga no desempenho do uso de OR (que ignora o uso do índice). A desvantagem é a quantidade de espaço temporário usado se o conjunto de dados for muito grande e um estiver próximo à última página. Não testei o desempenho do cursor nesse caso, mas pode ser melhor.
Observe que essa abordagem pode ser otimizada para a primeira página de dados. Além disso, ROWCOUNT foi usado, pois o TOP não aceita uma variável no SQL Server 2000.
fonte
A melhor maneira de paginar no sql server 2012 é usando deslocamento e busca a seguir em um procedimento armazenado. Palavra - chave OFFSET - Se usarmos offset com a cláusula order by, a consulta ignorará o número de registros que especificamos nas Linhas OFFSET n.
FETCH NEXT Keywords - Quando usamos o Fetch Next apenas com uma cláusula order by, ele retorna o número de linhas que você deseja exibir na paginação, sem Offset, o SQL gera um erro. Aqui está o exemplo dado abaixo.
você pode executá-lo da seguinte maneira.
fonte
Estas são minhas soluções para paginar o resultado da consulta no lado do servidor SQL. essas abordagens são diferentes entre o SQL Server 2008 e 2012. Além disso, adicionei o conceito de filtragem e ordem com uma coluna. É muito eficiente quando você está paginando, filtrando e solicitando no seu GridView.
Antes do teste, você deve criar uma tabela de amostra e inserir alguma linha nesta tabela: (No mundo real, você deve alterar a cláusula Where considerando os campos da tabela e talvez tenha alguma junção e subconsulta na parte principal do select)
Em todas essas amostras, quero consultar 200 linhas por página e estou buscando a linha para o número de página 1200.
No SQL Server 2008, você pode usar o conceito CTE. Por isso, escrevi dois tipos de consulta para o SQL Server 2008+
- SQL Server 2008 ou superior
E segunda solução com CTE no SQL server 2008+
- SQL Server 2012 ou superior
fonte
Tente esta abordagem:
fonte
No caso de uso, o seguinte parece ser fácil de usar e rápido. Basta definir o número da página.
também sem CTE
fonte
Bem, eu usei o seguinte exemplo de consulta no meu banco de dados SQL 2000, ele funciona bem para o SQL 2005 também. O poder que ele oferece é de ordem dinâmica, usando várias colunas. Eu lhe digo ... isso é poderoso :)
A melhor parte é que sp_executesql armazena em cache chamadas posteriores, desde que você passe os mesmos parâmetros, ou seja, gere o mesmo texto sql.
fonte
irá reiniciar o idx quando se trata de diferentes init_id
fonte
Para a
ROW_NUMBER
técnica, se você não tiver uma coluna de classificação para usar, poderá usar oCURRENT_TIMESTAMP
seguinte:Isso funcionou bem para mim em pesquisas de tamanhos de tabela de até 700.000.
Isso busca registros de 11 a 30.
fonte
fonte
Este bit oferece a capacidade de paginar usando o SQL Server e versões mais recentes do MySQL e carrega o número total de linhas em cada linha. Usa sua chave primária para contar o número de linhas exclusivas.
fonte
Esta é uma duplicata da antiga questão da SO de 2012: maneira eficiente de implementar a paginação
Aqui, o tópico é discutido em maiores detalhes e com abordagens alternativas.
fonte
A partir de 2012, podemos usar
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
fonte
Você não especificou o idioma nem o driver que está usando. Portanto, estou descrevendo isso de forma abstrata.
fonte