Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Maneira eficiente de obter @@rowcount de uma consulta usando row_number


Ao longo dos anos, uma pilha de suor do desenvolvedor foi aplicada em conjuntos de resultados de paginação de forma eficiente. No entanto, não há uma resposta - depende do seu caso de uso. Parte do caso de uso é obter sua página com eficiência, parte é descobrir quantas linhas estão em um conjunto de resultados completo. Sinto muito se me desviar um pouco da paginação, mas os dois estão muito bem acoplados em minha mente.

Existem muitas estratégias, a maioria das quais é ruim se você tiver algum tipo de volume de dados e não se encaixar no caso de uso. Embora esta não seja uma lista completa, a seguir estão algumas das opções .....

Executar Count(*) separado

  • execute uma consulta separada que faz um simples "selecionar contagem(*) de MinhaTabela"
  • simples e fácil para uma mesa pequena
  • bom em uma tabela grande não filtrada que seja estreita ou tenha um índice compacto não clusterizado que você pode usar
  • quebra quando você tem um WHERE/JOIN complicado critérios porque executar o WHERE/JOIN duas vezes é caro.
  • se divide em um índice amplo porque o número de leituras aumenta.

Combinar ROW_Number() OVER() e COUNT(1) OVER(PARTITION By 1)

  • Isso foi sugerido por @RBarryYoung. Tem a vantagem de ser simples de implementar e muito flexível.
  • A desvantagem é que há muitas razões pelas quais isso pode se tornar extremamente caro rapidamente.
  • Por exemplo, em um banco de dados que estou trabalhando atualmente, há uma tabela de mídia com cerca de 6.000 linhas. Não é particularmente amplo, possui um PK inteiro agrupado e, além de um índice exclusivo compacto. No entanto, um simples COUNT(*) OVER(PARTITION BY 1) as TotalRows resulta em ~12.000 leituras. Compare isso com um simples SELECT COUNT(*) FROM Media -- 12 leituras. Uauzers.

Tabelas temporárias/variáveis ​​de tabela

  • Existem muitas estratégias que pegam um conjunto de resultados e inserem chaves ou segmentos de resultados relevantes em tabelas temporárias/variáveis ​​de tabela.
  • Para conjuntos de resultados de tamanho pequeno/médio, isso pode fornecer ótimos resultados.
  • Esse tipo de estratégia funciona em praticamente qualquer plataforma/versão do SQL.
  • Operar em um conjunto de resultados várias vezes (muitas vezes um requisito) também é fácil.
  • A desvantagem é quando se trabalha com grandes conjuntos de resultados... inserir alguns milhões de linhas em uma tabela temporária tem um custo.
  • Para agravar o problema, em um sistema de alto volume, a pressão no TempDB pode ser um fator e tanto, e as tabelas temporárias funcionam efetivamente no TempDB.

Soma Gaussiana / Número de Linha Dupla

  • Esta ideia depende de subconjunto de algo que o matemático Gauss descobriu (como somar uma série de números). O subconjunto é como obter a contagem de linhas de qualquer ponto da tabela.
  • De uma série de números (Row_Number() ) a contagem de linhas de 1 a N é (N + 1) - 1 . Mais explicações nos links.
  • A fórmula parece que resultaria em apenas N, mas se você continuar com a fórmula, coisas interessantes acontecem, você pode descobrir a contagem de linhas de uma página no meio da tabela.
  • O resultado líquido é que você faz ROW_Number() OVER(Order by ID) e ROW_Number() OVER(Order by ID DESC) em seguida, some os dois números e subtraia 1.
  • Usando minha tabela de mídia como exemplo, minhas leituras caíram de 12.000 para cerca de 75.
  • Em uma página maior, você acabou repetindo dados muitas vezes, mas o deslocamento nas leituras pode valer a pena.
  • Não testei isso em muitos cenários, então pode desmoronar em outros cenários.

Topo (@n) / SET ROWCOUNT

  • Essas não são estratégias específicas em si, mas são otimizações baseadas no que sabemos sobre o otimizador de consulta.
  • O uso criativo de Top(@n) [top pode ser uma variável no SQL 2008] ou SET ROWCOUNT pode reduzir seu conjunto de trabalho ... mesmo se você estiver puxando uma página intermediária de um conjunto de resultados, ainda poderá restringir o resultado
  • Essas ideias funcionam devido ao comportamento do otimizador de consulta...um service pack/hotfix pode alterar o comportamento (embora provavelmente não).
  • Em certas instâncias, SET ROWCOUNT pode ser um pouco preciso
  • Essa estratégia não leva em conta a contagem completa de linhas, apenas torna a paginação mais eficiente

Então, o que um desenvolvedor deve fazer?


Leia meu bom homem, leia. Aqui estão alguns artigos em que me apoiei...

Espero que ajude.