Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Moyen efficace d'obtenir @@rowcount à partir d'une requête utilisant row_number

Au fil des ans, un tas de sueur de développeur a été consacré à la pagination efficace des ensembles de résultats. Pourtant, il n'y a pas de réponse unique - cela dépend de votre cas d'utilisation. Une partie du cas d'utilisation consiste à obtenir votre page efficacement, une partie consiste à déterminer le nombre de lignes dans un ensemble de résultats complet. Désolé si je m'égare un peu dans la pagination, mais les deux sont assez étroitement liés dans mon esprit.

Il existe de nombreuses stratégies, dont la plupart sont mauvaises si vous avez un volume de données quelconque et ne correspondent pas au cas d'utilisation. Bien que cette liste ne soit pas complète, voici quelques-unes des options .....

Exécuter un Count(*) séparé

  • exécuter une requête distincte qui fait un simple "select count(*) from MyTable"
  • simple et facile pour une petite table
  • bon sur une grande table non filtrée qui est étroite ou qui a un index compact non clusterisé que vous pouvez utiliser
  • tombe en panne lorsque vous avez un WHERE/JOIN compliqué car l'exécution de WHERE/JOIN le double coûte cher.
  • tombe en panne sur un index large car le nombre de lectures augmente.

Combiner ROW_Number() OVER() et COUNT(1) OVER(PARTITION By 1)

  • Ceci a été suggéré par @RBarryYoung. Il a l'avantage d'être simple à mettre en œuvre et très flexible.
  • L'inconvénient est qu'il existe de nombreuses raisons pour lesquelles cela peut rapidement devenir extrêmement coûteux.
  • Par exemple, dans une base de données sur laquelle je travaille actuellement, il y a une table Media avec environ 6000 lignes. Il n'est pas particulièrement large, a un PK entier en cluster et, ainsi qu'un index unique compact. Pourtant, un simple COUNT(*) OVER(PARTITION BY 1) as TotalRows donne environ 12 000 lectures. Comparez cela à un simple SELECT COUNT(*) FROM Media -- 12 lectures. Wowzers.

Tables temporaires / Variables de table

  • Il existe de nombreuses stratégies qui prennent un ensemble de résultats et insèrent des clés ou des segments de résultats pertinents dans des tables temporaires/variables de table.
  • Pour les ensembles de résultats de petite/moyenne taille, cela peut donner d'excellents résultats.
  • Ce type de stratégie fonctionne sur presque toutes les plates-formes/versions de SQL.
  • Il est également facile d'opérer plusieurs fois sur un ensemble de résultats (souvent une exigence).
  • L'inconvénient est que lorsque vous travaillez avec de grands ensembles de résultats... l'insertion de quelques millions de lignes dans une table temporaire a un coût.
  • Pour aggraver le problème, dans un système à volume élevé, la pression sur TempDB peut être un facteur important, et les tables temporaires fonctionnent efficacement dans TempDB.

Somme gaussienne / Nombre de lignes doubles

  • Cette idée repose sur sous-ensemble de quelque chose que le mathématicien Gauss a compris (comment additionner une série de nombres). Le sous-ensemble est de savoir comment obtenir le nombre de lignes à partir de n'importe quel point du tableau.
  • À partir d'une série de nombres (Row_Number() ) le nombre de lignes pour 1 à N est (N + 1) - 1 . Plus d'explications dans les liens.
  • La formule semble se résumer à N, mais si vous vous en tenez à la formule, des choses intéressantes se produisent, vous pouvez déterminer le nombre de lignes à partir d'une page au milieu du tableau.
  • Le résultat net est que vous faites ROW_Number() OVER(Order by ID) et ROW_Number() OVER(Order by ID DESC) puis additionnez les deux nombres et soustrayez 1.
  • En prenant mon tableau Media comme exemple, mes lectures sont passées de 12 000 à environ 75.
  • Dans une page plus grande, vous avez fini par répéter des données plusieurs fois, mais le décalage des lectures peut en valoir la peine.
  • Je n'ai pas testé cela sur trop de scénarios, il peut donc s'effondrer dans d'autres scénarios.

Haut (@n) / DÉFINIR ROWCOUNT

  • Il ne s'agit pas de stratégies spécifiques en soi, mais d'optimisations basées sur ce que nous savons de l'optimiseur de requêtes.
  • L'utilisation créative de Top(@n) [top peut être une variable dans SQL 2008] ou SET ROWCOUNT peut réduire votre ensemble de travail... même si vous tirez une page du milieu d'un ensemble de résultats, vous pouvez toujours affiner le résultat
  • Ces idées fonctionnent en raison du comportement de l'optimiseur de requête... un service pack/correctif peut modifier le comportement (mais probablement pas).
  • Dans certains cas, SET ROWCOUNT peut être un peu inexact
  • Cette stratégie ne tient pas compte de l'obtention du nombre total de lignes, mais rend simplement la pagination plus efficace

Qu'est-ce qu'un développeur doit faire ?

Lisez mon bonhomme, lisez. Voici quelques articles sur lesquels je me suis appuyé...

J'espère que ça aide.