129 votes

Pourquoi les gens détestent-ils tant les curseurs SQL ?

Je peux comprendre que l'on veuille éviter d'avoir à utiliser un curseur en raison de la surcharge et des inconvénients, mais il semble que l'on assiste à une véritable phobie du curseur et que les gens se donnent beaucoup de mal pour éviter d'avoir à en utiliser un.

Par exemple, une question demandait comment faire quelque chose de manifestement trivial avec un curseur et la réponse acceptée proposait d'utiliser une requête récursive CTE (Common Table Expression) avec une fonction récursive personnalisée, même si cela limite le nombre de lignes pouvant être traitées à 32 (en raison de la limite d'appels de fonctions récursives dans le serveur SQL). Cela me semble être une très mauvaise solution pour la longévité du système, sans parler de l'effort considérable que cela représente pour éviter d'utiliser un simple curseur.

Quelle est la raison de ce niveau de haine insensée ? Une "autorité reconnue" a-t-elle émis une fatwa contre les maudisseurs ? Un mal indicible rôde-t-il dans le cœur des maudits, corrompant la morale des enfants ou quelque chose du genre ?

Question Wiki, plus intéressée par la réponse que par le représentant.

Informations connexes :

Curseurs d'avance rapide de SQL Server

EDIT : je vais être plus précis : Je comprends que les curseurs ne doivent pas être utilisés à la place des opérations relationnelles normales ; c'est une évidence. Ce que je ne comprends pas, ce sont les gens qui font tout pour éviter les curseurs comme s'ils avaient des poux ou quelque chose comme ça, même quand un curseur est une solution plus simple et/ou plus efficace. C'est la haine irrationnelle qui me déconcerte, pas l'efficacité technique évidente.

1 votes

Je pense que votre éditorial en dit long... En presque dans toutes les situations (que j'ai rencontrées), il existe un moyen de remplacer un curseur par une situation basée sur un ensemble plus performant. Vous dites que c'est une évidence, mais vous comprenez la différence.

7 votes

J'adore les étiquettes de cette question !

2 votes

La partie concernant les limites récursives de l'ETC étant 32 est un non-sens. Vous pensez sans doute aux déclencheurs récursifs et à la fonction max @@NESTLEVEL de 32 . Il peut être défini dans la requête avec OPTION (MAXRECURSION N) avec défaut 100 y 0 c'est-à-dire illimité.

74voto

S.Lott Points 207588

La "surcharge" des curseurs fait simplement partie de l'API. Les curseurs sont la façon dont certaines parties du SGBDR fonctionnent sous le capot. Souvent, les CREATE TABLE y INSERT avoir SELECT et l'implémentation est celle, évidente, du curseur interne.

L'utilisation d'"opérateurs basés sur des ensembles" de niveau supérieur permet de regrouper les résultats du curseur en un seul ensemble de résultats, ce qui réduit les allers-retours au niveau de l'API.

Les curseurs sont antérieurs aux langages modernes qui fournissent des collections de premier ordre. Les anciens langages C, COBOL, Fortran, etc., devaient traiter les lignes une par une parce qu'il n'existait pas de notion de "collection" utilisable à grande échelle. Java, C#, Python, etc., disposent de structures de liste de première classe pour contenir les ensembles de résultats.

La question de la lenteur

Dans certains cercles, les jointures relationnelles sont un mystère, et les gens écrivent des curseurs imbriqués plutôt qu'une simple jointure. J'ai vu des opérations de boucles imbriquées vraiment épiques écrites sous la forme de nombreux curseurs. Ce qui va à l'encontre de l'optimisation du SGBDR. Et s'exécutant très lentement.

De simples réécritures SQL visant à remplacer les boucles de curseur imbriquées par des jointures et une seule boucle de curseur plate peuvent faire fonctionner les programmes en un centième de temps. [Ils pensaient que j'étais le dieu de l'optimisation. Tout ce que j'ai fait, c'est remplacer les boucles imbriquées par des jointures. Ils utilisaient encore des curseurs].

Cette confusion conduit souvent à une mise en accusation des curseurs. Or, ce n'est pas le curseur, c'est l'utilisation abusive du curseur qui pose problème.

La question de la taille

Pour les ensembles de résultats vraiment épiques (c'est-à-dire le transfert d'une table dans un fichier), les curseurs sont essentiels. Les opérations basées sur les ensembles ne peuvent pas matérialiser les ensembles de résultats très volumineux sous la forme d'une collection unique en mémoire.

Alternatives

J'essaie d'utiliser une couche ORM autant que possible. Mais cela a deux objectifs. Premièrement, les curseurs sont gérés par le composant ORM. Deuxièmement, le SQL est séparé de l'application dans un fichier de configuration. Ce n'est pas que les curseurs soient mauvais. C'est que coder toutes ces ouvertures, fermetures et extractions n'est pas une programmation à valeur ajoutée.

3 votes

"Les curseurs sont la façon dont le SGBDR fonctionne sous le capot. Si vous voulez parler spécifiquement de SQL Server, d'accord, je n'en sais rien. Mais j'ai travaillé sur le fonctionnement interne de plusieurs SGBDR (et SGBDO) (sous Stonebraker) et aucun d'entre eux n'a fait cela. Par exemple, Ingres utilise ce qui équivaut à des "ensembles de résultats" de tuples en interne.

0 votes

@Richard T : Je travaille à partir d'informations de seconde main sur la source des SGBDR ; je vais modifier ma déclaration.

2 votes

"J'ai vu des opérations de boucles imbriquées vraiment épiques écrites sous la forme de nombreux curseurs." Je continue à en voir aussi. C'est difficile à croire.

42voto

Galwegian Points 29966

Les curseurs obligent les gens à appliquer de manière excessive un état d'esprit procédural à un environnement basé sur un ensemble de règles.

Et ils sont LENT ! !!

De SQLTeam :

Veuillez noter que les curseurs sont la manière la plus LENTE d'accéder aux données dans SQL Server. Ils ne doivent être utilisés que lorsque vous avez vraiment besoin à la fois. La seule raison à laquelle je peux penser est d'appeler une procédure stockée sur chaque ligne. Dans le fichier C Article sur la performance I que les curseurs sont o plus lent que les solutions basées sur des ensembles .

6 votes

Cet article date de 7 ans, pensez-vous que les choses ont pu changer entre-temps ?

1 votes

Je pense également que les curseurs sont vraiment lents et qu'il faut les éviter, en général. Cependant, si l'OP faisait référence à la question que je pense qu'il posait, alors un curseur était la bonne solution dans ce cas (flux d'enregistrements un par un en raison de contraintes de mémoire).

0 votes

L'article mis à jour ne corrige pas les mesures de vitesse relative, mais il fournit quelques bonnes optimisations et alternatives. Notez que l'article original indique que les curseurs sont 50 fois plus rapides que les boucles while, ce qui est intéressant.

20voto

davidcl Points 709

La réponse ci-dessus indique que "les curseurs sont le moyen le plus LENT d'accéder aux données dans le serveur SQL... les curseurs sont plus de trente fois plus lents que les alternatives basées sur les ensembles".

Cette affirmation peut être vraie dans de nombreuses circonstances, mais elle est problématique en tant qu'affirmation générale. Par exemple, j'ai fait bon usage des curseurs dans des situations où je voulais effectuer une opération de mise à jour ou de suppression affectant de nombreuses lignes d'une grande table qui fait l'objet de lectures constantes en production. L'exécution d'une procédure stockée qui effectue ces mises à jour une ligne à la fois finit par être plus rapide que les opérations basées sur des ensembles, parce que l'opération basée sur des ensembles entre en conflit avec l'opération de lecture et finit par causer d'horribles problèmes de verrouillage (et peut tuer entièrement le système de production, dans les cas extrêmes).

En l'absence d'autres activités dans la base de données, les opérations basées sur les ensembles sont universellement plus rapides. Dans les systèmes de production, cela dépend.

1 votes

On dirait l'exception qui confirme la règle.

6 votes

@[Joel Coehoorn] : Je n'ai jamais compris ce dicton.

2 votes

@[Steven A. Lowe] phrases.org.uk/meanings/exception-qui-prouve-la-règle.html comprendre l'exception comme "ce qui est omis" et noter que la règle ici est quelque chose comme "dans la plupart des situations, les curseurs sont mauvais".

9voto

Cade Roux Points 53870

L'optimiseur ne peut souvent pas utiliser l'algèbre relationnelle pour transformer le problème lorsqu'une méthode de curseur est utilisée. Souvent, un curseur est un excellent moyen de résoudre un problème, mais SQL est un langage déclaratif et il y a beaucoup d'informations dans la base de données, des contraintes aux statistiques et aux index, ce qui signifie que l'optimiseur a beaucoup d'options pour résoudre le problème, alors qu'un curseur dirige presque explicitement la solution.

9voto

davidcl Points 709

Les curseurs ont tendance à être utilisés par les développeurs SQL débutants là où des opérations basées sur des ensembles seraient plus efficaces. En particulier lorsque les personnes apprennent SQL après avoir appris un langage de programmation traditionnel, la mentalité "itérer sur ces enregistrements" tend à les amener à utiliser les curseurs de manière inappropriée.

La plupart des ouvrages sérieux sur le langage SQL comportent un chapitre préconisant l'utilisation des curseurs ; les ouvrages bien rédigés indiquent clairement que les curseurs ont leur place, mais qu'ils ne doivent pas être utilisés pour les opérations basées sur des ensembles.

Il existe manifestement des situations où les curseurs sont le bon choix, ou du moins un bon choix.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X