Je peux comprendre de vouloir éviter d'avoir à utiliser un curseur en raison de la surcharge et des inconvénients, mais il semble qu'il y ait une grave phobie-manie du curseur où les gens se donnent beaucoup de mal pour éviter d'en utiliser un.
Par exemple, une question demandait comment faire quelque chose de évidemment trivial avec un curseur et la réponse acceptée proposée à l'aide d'une requête récursive d'expression de table commune (CTE) avec une fonction personnalisée récursive, même si cela limite le nombre de lignes pouvant être traitées à 32 (en raison de la limite d'appel de fonction récursive dans le serveur SQL). Cela me semble être une solution terrible pour la longévité du système, sans parler d'un effort énorme juste pour éviter d'utiliser un simple curseur.
Quelle est la raison de ce niveau de haine insensée? Une «autorité notoire» a-t-elle émis une fatwa contre les curseurs? Un mal indicible se cache-t-il au cœur des curseurs qui corrompt 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 SQL Server
EDIT: permettez-moi d'ê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, c'est que les gens se mettent en quatre pour éviter les curseurs comme s'ils avaient des cooties ou quelque chose du genre, même lorsqu'un curseur est une solution plus simple et / ou plus efficace. C'est la haine irrationnelle qui me déroute, pas les efficiences techniques évidentes.
32
est absurde. Vous pensez probablement aux déclencheurs récursifs et au maximum@@NESTLEVEL
de32
. Il peut être défini dans la requête avecOPTION (MAXRECURSION N)
par défaut100
et0
signifiant illimité.Réponses:
La "surcharge" avec les curseurs fait simplement partie de l'API. Les curseurs sont la façon dont certaines parties du SGBDR fonctionnent sous le capot. Souvent
CREATE TABLE
etINSERT
ont desSELECT
déclarations, et la mise en œuvre est la mise en œuvre évidente du curseur interne.L'utilisation d '«opérateurs basés sur des ensembles» de niveau supérieur regroupe les résultats du curseur dans un ensemble de résultats unique, ce qui signifie moins de va-et-vient d'API.
Les curseurs sont antérieurs aux langages modernes qui fournissent des collections de première classe. Les anciens C, COBOL, Fortran, etc., devaient traiter les lignes une par une car il n'y avait pas de notion de «collection» qui pourrait être largement utilisée. Java, C #, Python, etc., ont des structures de liste de première classe pour contenir des ensembles de résultats.
Le problème lent
Dans certains cercles, les jointures relationnelles sont un mystère et les gens écriront 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. Vaincre une optimisation SGBDR. Et courir très lentement.
Des réécritures SQL simples pour remplacer les boucles de curseur imbriquées par des jointures et une seule boucle de curseur plat peuvent faire exécuter les programmes 100 fois. [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. Curseurs encore utilisés.]
Cette confusion conduit souvent à une mise en accusation des curseurs. Cependant, ce n'est pas le curseur, c'est la mauvaise utilisation du curseur qui est le problème.
Le problème de la taille
Pour des ensembles de résultats vraiment épiques (c'est-à-dire, vider une table dans un fichier), les curseurs sont essentiels. Les opérations basées sur des ensembles ne peuvent pas matérialiser des ensembles de résultats vraiment volumineux sous la forme d'une seule collection en mémoire.
Alternatives
J'essaie d'utiliser une couche ORM autant que possible. Mais cela a deux objectifs. Tout d'abord, 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 tous ces ouvre, ferme et récupère n'est pas une programmation à valeur ajoutée.
la source
Les curseurs incitent les gens à appliquer excessivement un état d'esprit procédural à un environnement basé sur des ensembles.
Et ils sont LENTS !!!
De SQLTeam :
la source
Il y a une réponse ci-dessus qui dit que "les curseurs sont le moyen le plus lent d'accéder aux données à l'intérieur de SQL Server ... les curseurs sont plus de trente fois plus lents que les alternatives basées sur des ensembles."
Cette déclaration peut être vraie dans de nombreuses circonstances, mais en tant que déclaration générale, elle est problématique. Par exemple, j'ai fait bon usage des curseurs dans les situations où je souhaite effectuer une opération de mise à jour ou de suppression affectant de nombreuses lignes d'une grande table qui reçoit des lectures de production constantes. 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, car 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 complètement le système de production, dans des cas extrêmes).
En l'absence d'autres activités de base de données, les opérations basées sur des ensembles sont universellement plus rapides. Dans les systèmes de production, cela dépend.
la source
Les curseurs ont tendance à être utilisés par les développeurs SQL débutants dans des endroits où les opérations basées sur des ensembles seraient meilleures. En particulier, lorsque les gens apprennent SQL après avoir appris un langage de programmation traditionnel, la mentalité «itérer sur ces enregistrements» a tendance à conduire les gens à utiliser les curseurs de manière inappropriée.
Les livres SQL les plus sérieux incluent un chapitre enjoignant l'utilisation de curseurs; ceux bien écrits indiquent clairement que les curseurs ont leur place mais ne doivent pas être utilisés pour des opérations basées sur des ensembles.
Il y a évidemment des situations où les curseurs sont le bon choix, ou du moins un bon choix.
la source
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 assez explicitement la solution.
la source
Dans Oracle PL / SQL, les curseurs n'entraîneront pas de verrous de table et il est possible d'utiliser la collecte en masse / la récupération en masse.
Dans Oracle 10, le curseur implicite souvent utilisé
récupère implicitement 100 lignes à la fois. Une collecte / extraction en bloc explicite est également possible.
Cependant, les curseurs PL / SQL sont quelque chose de dernier recours, utilisez-les lorsque vous ne parvenez pas à résoudre un problème avec SQL basé sur des ensembles.
Une autre raison est la parallélisation, il est plus facile pour la base de données de paralléliser de grandes instructions basées sur des ensembles que du code impératif ligne par ligne. C'est la même raison pour laquelle la programmation fonctionnelle devient de plus en plus populaire (Haskell, F #, Lisp, C # LINQ, MapReduce ...), la programmation fonctionnelle facilite la parallélisation. Le nombre de processeurs par ordinateur augmente donc la parallélisation devient de plus en plus un problème.
la source
En général, car sur une base de données relationnelle, les performances du code utilisant des curseurs sont d'un ordre de grandeur pire que les opérations basées sur des ensembles.
la source
Les réponses ci-dessus n'ont pas suffisamment souligné l'importance du verrouillage. Je ne suis pas un grand fan des curseurs car ils entraînent souvent des verrous au niveau de la table.
la source
Pour ce que ça vaut, j'ai lu que le "un" place un curseur exécutera son homologue basé sur un ensemble est dans un total courant. Sur une petite table, la vitesse de sommation des lignes sur l'ordre par colonnes favorise l'opération basée sur l'ensemble, mais à mesure que la taille de la table augmente, le curseur deviendra plus rapide car il peut simplement porter la valeur totale en cours au prochain passage du boucle. Maintenant, là où vous devriez faire un total cumulé, c'est un argument différent ...
la source
Je suis d'accord avec l'article sur cette page:
http://weblogs.sqlteam.com/jeffs/archive/2008/06/05/sql-server-cursor-removal.aspx
la source
En dehors des (non) problèmes de performance, je pense que le plus gros défaut des curseurs est qu'ils sont difficiles à déboguer. Surtout par rapport au code dans la plupart des applications clientes où le débogage a tendance à être relativement facile et les fonctionnalités linguistiques ont tendance à être beaucoup plus faciles. En fait, je soutiens que presque tout ce que l'on fait en SQL avec un curseur devrait probablement se produire dans l'application cliente en premier lieu.
la source
Pouvez-vous publier cet exemple de curseur ou un lien vers la question? Il existe probablement un moyen encore meilleur qu'un CTE récursif.
En plus d'autres commentaires, les curseurs utilisés de manière incorrecte (ce qui est souvent le cas) provoquent des verrous de page / ligne inutiles.
la source
Vous auriez probablement pu conclure votre question après le deuxième paragraphe, plutôt que de qualifier les gens de «fous» simplement parce qu'ils ont un point de vue différent de celui que vous faites et d'essayer de se moquer des professionnels qui peuvent avoir une très bonne raison de ressentir ce qu'ils font.
Quant à votre question, bien qu'il y ait certainement des situations où un curseur peut être appelé, d'après mon expérience, les développeurs décident qu'un curseur "doit" être utilisé LOIN plus souvent que ce n'est le cas en réalité. La chance que quelqu'un se trompe du côté d'une utilisation excessive des curseurs par rapport à ne pas les utiliser quand ils le devraient est BEAUCOUP plus élevée à mon avis.
la source
fondamentalement 2 blocs de code qui font la même chose. c'est peut-être un exemple un peu étrange mais cela prouve le point. SQL Server 2005:
la mise à jour unique prend 156 ms tandis que le curseur prend 2016 ms.
la source