8
votes

Avantages et inconvénients d'utiliser un curseur (dans SQL Server)

J'ai posé une question ici Utilisation du curseur dans les bases de données OLTP (SQL Server) < / a>

où les gens ont répondu dire que les curseurs ne doivent jamais être utilisés.

Je pense que les curseurs sont des outils très puissants destinés à être utilisés (je ne pense pas que Microsoft prend en charge les curseurs des mauvais développeurs) .supospose Vous avez une table où la valeur d'une colonne d'affilée dépend de la valeur de la valeur de la valeur la même colonne de la ligne précédente. S'il s'agit d'un processus de fin de temps unique, ne pensez-vous pas que l'utilisation d'un curseur serait un choix acceptable?

Sur le dessus de ma tête, je peux penser à quelques scénarios où je pense qu'il ne devrait pas y avoir de honte à l'aide de curseurs. S'il vous plaît laissez-moi savoir si vous vous sentez autrement.

1> Un processus de bout en bout unique pour nettoyer les mauvaises données qui complètent l'exécution en quelques minutes. 2> Processus de lots qui fonctionnent une fois dans une longue période (quelque chose comme une fois par an). Si dans les scénarios ci-dessus, il n'y a pas de tension visible sur les autres processus, ne serait-il pas déraisonnable de passer des heures supplémentaires à écrire du code pour éviter les curseurs? En d'autres termes, dans certains cas, le temps du développeur est plus important que la performance d'un processus qui n'a presque aucun impact sur rien d'autre.

À mon avis, ce serait des scénarios où vous devriez sérieusement essayer d'éviter d'utiliser un curseur. 1> Un processus stocké appelé à partir d'un site Web qui peut être appelé très souvent. 2> Un travail SQL qui fonctionnerait plusieurs fois par jour et consomme beaucoup de ressources.

Je pense que c'est très superficiel de faire une déclaration générale comme "les curseurs ne doivent jamais être utilisées" sans analyser la tâche à portée de main et le peser en réalité contre les alternatives.

S'il vous plaît laissez-moi savoir de vos pensées.


2 commentaires

On dirait que SQL Server 2012 prend en charge le cas d'obtenir la valeur de la ligne antérieure de manière basée sur une définition.


"Une procédure stockée appelée à partir d'un site Web" est trop vague. Si un curseur est le choix le plus raisonnable pour résoudre un problème et que la procédure doit être appelée à partir d'une page Web ...


5 Réponses :


6
votes

Le problème avec les curseurs dans SQL Server est que le moteur est installé en interne, contrairement à d'autres DBMS comme Oracle tels que le curseur basé en interne. Cela signifie que lorsque vous créez un curseur dans SQL Server, le stockage temporaire doit être créé et les Resultats basés sur l'ensemble doivent être copiés sur le stockage du curseur temporaire. Vous pouvez voir pourquoi cela serait coûteux tout de suite de la batte, de ne pas mentionner de traitement de ligne par ligne que vous pourriez faire au-dessus du curseur lui-même. La fin de la ligne est que le traitement basé sur un ensemble est plus efficace et que l'opération à base de curseur peut souvent être efficace à l'aide d'une table CTE ou TEMP.

Cela étant dit, il y a des cas où un curseur est probablement acceptable, comme vous l'avez dit pour des opérations unique. L'utilisation la plus courante que je puisse penser est dans un plan de maintenance où vous pouvez être itération via toutes les bases de données sur un serveur exécutant diverses tâches de maintenance. Tant que vous limitez votre utilisation et ne concevez pas d'applications entières autour de la transformation RBAR (rangée à la ligne d'angoissement), vous devriez être bien.


0 commentaires

3
votes

dans les curseurs généraux sont une mauvaise chose. Cependant, dans certains cas, il est plus pratique d'utiliser un curseur et, dans certains, il est encore plus rapide d'en utiliser un. Un bon exemple est un curseur à travers une table de contact envoyant des courriels en fonction de certains critères. (Ne pas ouvrir la question si l'envoi d'un courrier électronique de votre SGBD est une bonne idée - supposons simplement que ce soit pour le problème à la main.) Il n'y a aucun moyen d'écrire ce jeu. Vous pouvez utiliser un peu de scandale pour créer une solution installée pour générer SQL dynamique, mais une solution réelle basée sur un ensemble n'existe pas.

Cependant, un calcul impliquant la ligne précédente peut être effectué à l'aide d'une jointure auto. Qui est généralement encore plus rapide qu'un curseur.

Dans tous les cas, vous devez équilibrer les efforts déployés dans le développement d'une solution plus rapide. Si personne ne se soucie, si vous traitez des courses en 1 minute ou en une heure, utilisez ce qui obtient le travail effectué le plus rapidement. Si vous bouclez dans un jeu de données qui pousse au fil du temps comme une table [COMMANDES], essayez de rester à l'écart du curseur si possible. Si vous n'êtes pas sûr, effectuez un test de performance comparant une base de curseur avec une solution à base de données sur plusieurs tailles de données significativement différentes.


1 commentaires

+1 Je suis d'accord avec une grande partie de cela que vous avez dit, bien que les calculs de ligne précédents puissent être assez complexes à écrire avec la plupart des solutions basées sur les installations, par exemple les totaux d'exécution (élimination des fonctionnalités de prélèvement pour maintenant).



12
votes

Il existe plusieurs scénarios où les curseurs fonctionnent réellement mieux que les équivalents à base d'ensemble. Les totaux en cours d'exécution sont ceux qui viennent toujours à l'esprit - recherchent les mots d'Izik sur cela (et ignorez-les impliquant que SQL Server 2012, qui ajoute de nouvelles fonctions de fenêtres qui donnent des curseurs une course à leur argent dans cette situation).

Un Les gros problèmes que les personnes souffrent de curseurs sont qu'ils effectuent lentement, ils utilisent un stockage temporaire, etc. Ceci est partiellement parce que la syntaxe par défaut est un curseur global avec toutes sortes d'options par défaut inefficace. La prochaine fois que vous ferez quelque chose avec un curseur qui n'a pas besoin de faire des choses comme update ... où le courant de (que j'ai pu éviter toute marée carrière), donnez-la Un shake équitable en comparant ces deux options de syntaxe: xxx

En fait, la première version représente un bogue dans la procédure stockée sans papiers SP_MSForeachdb, ce qui permet d'ignorer des bases de données si l'état de toute base de données changements pendant l'exécution. J'ai ensuite écrit ma propre version de la procédure stockée (voir ici ) qui corrigeait le bogue (simplement en utilisant la dernière version de la syntaxe ci-dessus) et ajouté plusieurs paramètres à contrôler les bases de données que les bases de données seraient choisies.

Beaucoup de gens Pensez qu'une méthodologie n'est pas un curseur car il ne dit pas déclarer le curseur . J'ai vu que des gens affirment que la boucle de temps est plus rapide qu'un curseur ( que j'espère que j'ai dissipé ici ) ou que l'utilisation de pour XML chemin pour effectuer la concaténation du groupe ne fonctionne pas un curseur caché opération. En regardant le plan dans beaucoup de cas montrera la vérité.

Dans de nombreux cas, des curseurs sont utilisés lorsque la base est davantage appropriée. Mais il existe de nombreux cas d'utilisation valides où un équivalent à base d'ensemble est beaucoup plus compliqué à écrire, car l'optimiseur de générer un plan pour, à la fois ou non possible (par exemple, des tâches de maintenance où vous êtes en boucle via des tables pour mettre à jour les statistiques, appeler une procédure stockée pour chaque valeur d'un résultat, etc.). Il en va de même pour beaucoup de grandes requêtes multi-tableaux où le plan devient trop monstrueux pour l'optimiseur à gérer. Dans ces cas, il peut être préférable de vider certains des résultats intermédiaires dans une structure temporaire en premier. Il en va de même pour certains équivalents à base de curseurs basés sur des curseurs (comme des totaux d'exécution). J'ai également écrit sur l'autre sens, où les gens pensent presque toujours instinctivement d'utiliser une boucle / curseur et il y a Alternatives à base de plons intelligents qui sont beaucoup mieux .

Mise à jour 2013-07-25 < / p>

Je voulais juste ajouter quelques publications de blog supplémentaires que j'ai écrites sur des curseurs, quelles options vous devriez utiliser si vous DO devez les utiliser et utiliser des requêtes à base de réglage au lieu de Des boucles pour générer des ensembles:

meilleures approches Pour les totaux d'exécution - mis à jour pour SQL Server 2012

Quel impact peut avoir différentes options de curseur?

Générer un ensemble ou une séquence sans boucles: [Partie 1] [Partie 2] [Partie 3]


0 commentaires

0
votes

Ils sont nécessaires pour des choses comme une pivotement dynamique SQL, mais vous devriez essayer d'éviter les utiliser autant que possible.


0 commentaires

0
votes

J'avais toujours détesté des curseurs à cause de leurs performances lentes. Cependant, j'ai trouvé que je n'ai pas complètement compris les différents types de curseurs et que, dans certains cas, les curseurs sont une solution viable.

Lorsque vous avez un problème d'entreprise qui ne peut être résolu que par le traitement d'une ligne à la fois, un curseur est approprié.

afin d'améliorer les performances avec le curseur, modifiez le type de curseur que vous utilisez. Quelque chose que je ne connaissais pas était, si vous ne spécifiez pas le type de curseur que vous déclarez, vous obtenez le type optimiste dynamique par défaut, c'est celui qui est le plus lent pour la performance, car il fait beaucoup de travail sous la hotte. . Cependant, en déclarant votre curseur comme un type différent, dites un curseur statique, il a de très bonnes performances.

Voir ces articles pour une explication plus complète:

La vérité sur les curseurs: Partie I

La vérité sur les curseurs: Partie II

La vérité sur les curseurs: Partie III

Je pense que le plus gros cont des curseurs est la performance, cependant, ne posant pas une tâche dans une approche établie aurait probablement classé deuxième. Troisièmement serait la lisibilité et la mise en page des tâches car ils n'ont généralement pas beaucoup de commentaires utiles.

SQL Server est optimisé pour exécuter l'approche définie. Vous écrivez la requête pour renvoyer un ensemble de données de résultat, comme une jointure sur des tables, par exemple, mais le moteur d'exécution SQL Server détermine que la jointure à utiliser: Fusion de jointure, une jointure de boucle imbriquée ou une jointure de hachage. SQL Server détermine le meilleur algorithme de jonction possible en fonction des colonnes participantes, du volume de données, de la structure d'indexation et de l'ensemble des valeurs dans les colonnes participantes. Ainsi, l'utilisation d'une approche établie est généralement la meilleure approche de la performance sur l'approche du curseur de procédure.


0 commentaires