Como outros já apontaram, as consultas retornam resultados diferentes e estão comparando maçãs com laranjas.
Mas a questão subjacente permanece:o que é mais rápido:paginação orientada por conjunto de chaves ou paginação orientada por número de linha?
Paginação de conjunto de chaves
A paginação orientada por conjunto de chaves depende de lembrar as teclas superior e inferior da última página exibida e solicitar o conjunto de linhas seguinte ou anterior, com base no conjunto de chaves superior/último:
Próxima página:
select top (<pagesize>) ...
from <table>
where key > @last_key_on_current_page
order by key;
Página anterior:
select top (<pagesize>)
from <table>
where key < @first_key_on_current_page
order by key desc;
Essa abordagem tem duas vantagens principais sobre a abordagem ROW_NUMBER ou sobre a abordagem LIMIT equivalente do MySQL:
- está correto :ao contrário da abordagem baseada em número de linha, ele lida corretamente com novas entradas e entradas excluídas. A última linha da página 4 não aparece como primeira linha da página 5 apenas porque a linha 23 da página 2 foi excluída nesse meio tempo. Nem as linhas desaparecem misteriosamente entre as páginas. Essas anomalias são comuns com a abordagem baseada em número_linha, mas a solução baseada em conjunto de chaves faz um trabalho muito melhor para evitá-las.
- é rápido :todas as operações podem ser resolvidas com um posicionamento de linha rápido seguido por uma varredura de intervalo na direção desejada
No entanto, essa abordagem é difícil para implementar, difícil de entender pelo programador médio e não suportado pelas ferramentas.
Acionado por número de linha
Esta é a abordagem comum introduzida com consultas Linq:
select ...
from (
select ..., row_number() over (...) as rn
from table)
where rn between @firstRow and @lastRow;
(ou uma consulta semelhante usando TOP) Essa abordagem é fácil para implementar e é suportado por ferramentas (especificamente pelos operadores Linq .Limit e .Take). Mas essa abordagem é garantida para varrer o índice para contar as linhas. Essa abordagem geralmente funciona muito rápido para a página 1 e diminui gradualmente à medida que a página vai para números de página cada vez mais altos.
Como bônus, com esta solução é muito fácil alterar a ordem de classificação (basta alterar a cláusula OVER).
No geral, dada a facilidade das soluções baseadas em ROW_NUMBER(), o suporte que elas têm do Linq, a simplicidade de usar ordens arbitrárias para conjuntos de dados moderados as soluções baseadas em ROW_NUMBER são adequadas. Para conjuntos de dados grandes e muito grandes, ROW_NUMBER() pode ocorrer sérios problemas de desempenho.
Uma outra coisa a considerar é que muitas vezes há um padrão definido de acesso. Muitas vezes as primeiras páginas são quentes e as páginas depois de 10 são basicamente nunca visualizadas (por exemplo, posts mais recentes). Nesse caso, a penalidade que ocorre com ROW_NUMBER() por visitar as páginas inferiores (páginas de exibição para as quais um grande número de linhas deve ser contado para obter a linha de resultado inicial) pode ser ignorada.
E, finalmente, a paginação do conjunto de chaves é ótima para navegação de dicionário, que ROW_NUMBER() não pode acomodar facilmente. A navegação do dicionário é onde, em vez de usar o número da página, os usuários podem navegar para determinadas âncoras, como letras do alfabeto. Exemplo típico sendo um contato Rolodex como barra lateral, você clica em M e navega para o primeiro nome do cliente que começa com M.