web-dev-qa-db-fra.com

Quels sont les avantages de l'utilisation du curseur de base de données?

Il est basé sur la question d'entrevue que j'ai rencontrée.

Une définition très courte peut être

Il peut être utilisé pour manipuler les lignes renvoyées par une requête.

Outre l'utilisation du curseur (les points sont répertoriés ici sur MSDN), j'ai une question dans mon esprit que si nous pouvons effectuer toutes les opérations à l'aide d'une requête ou d'une procédure stockée (si je ne me trompe pas, Comme nous pouvons utiliser Transact-SQL pour ms-sql), y a-t-il un point concret que nous devrions utiliser le curseur?

41
Vikas

Utiliser des curseurs par rapport à de grands ensembles de résultats, c'est comme utiliser le streaming vidéo au lieu de télécharger une vidéo d'un seul coup et de la regarder lorsqu'elle a été téléchargée. Si vous téléchargez, vous devez avoir quelques Go d'espace et la patience d'attendre la fin du téléchargement. Maintenant, quelle que soit la vitesse de votre machine ou de votre réseau, tout le monde regarde un film à la même vitesse.

Normalement, toute requête est envoyée au serveur, exécutée et l'ensemble de résultats vous est envoyé sur le réseau, en une seule rafale d'activité. Le curseur vous donnera accès aux données ligne par ligne et ne diffusera chaque ligne que lorsque vous en aurez fait la demande (vous pourrez en fait les visualiser).

  • Un curseur peut vous faire gagner du temps - car vous n'avez pas besoin d'attendre le traitement et le téléchargement de votre jeu d'enregistrements complet
  • Cela vous fera économiser de la mémoire, à la fois sur le serveur et sur le client, car ils n'ont pas à consacrer une grande partie de la mémoire aux jeux de résultats
  • Équilibrez la charge de votre réseau et de votre serveur - Travailler en mode "rafale" est généralement plus efficace, mais il peut bloquer complètement votre serveur et votre réseau. De tels retards sont rarement souhaitables pour les environnements multi-utilisateurs. Le streaming laisse place à d'autres opérations.
  • Permet des opérations sur des tables interrogées (sous certaines conditions) qui n'affectent pas directement votre curseur. Ainsi, lorsque vous tenez un curseur sur une ligne, d'autres processus peuvent lire, mettre à jour et même supprimer d'autres lignes. Cela aide particulièrement avec les tables très occupées, de nombreuses lectures et écritures simultanées.

Ce qui nous amène cependant à quelques mises en garde:

  • Cohérence: à l'aide d'un curseur, vous n'opérez (généralement) pas sur un instantané cohérent des données, mais sur une ligne. Ainsi, vos garanties de concurrence/cohérence/isolation passent de la base de données entière (ACID) à une seule ligne. Vous pouvez généralement informer votre SGBD du niveau de concurrence que vous souhaitez, mais si vous êtes trop exigeant (verrouiller la table complète dans laquelle vous vous trouvez), vous gaspillerez de nombreuses économies de ressources côté serveur.

  • La transmission de chaque ligne par elle-même peut être très inefficace, car chaque paquet a une surcharge de négociation que vous pourriez éviter en envoyant de gros morceaux, peut-être compressés, de données par paquet. (Aucun serveur de base de données ou bibliothèque cliente n'est assez stupide pour transmettre chaque ligne individuellement, il y a mise en cache et segmentation aux deux extrémités, toujours, c'est pertinent.)

  • Les curseurs sont plus difficiles à bien faire. Considérez une requête avec un grand ensemble de résultats, vous motivant à utiliser un curseur, qui utilise une clause GROUP BY avec des fonctions d'agrégation. (De telles requêtes sont courantes dans les entrepôts de données). Le GROUP BY peut complètement mettre à la corbeille votre serveur, car il doit générer et stocker l'ensemble de résultats en une seule fois, peut-être même maintenir des verrous sur d'autres tables.

Règle générale:

  • Si vous travaillez sur de petits ensembles de résultats rapidement créés, n'utilisez pas de curseurs.
  • Les curseurs excellent sur les requêtes ad hoc, complexes (référentiellement), de nature séquentielle avec de grands ensembles de résultats et de faibles exigences de cohérence.

"Nature séquentielle" signifie qu'il n'y a pas de fonctions d'agrégation dans les lourdes clauses GROUP BY dans votre requête. Le serveur peut décider paresseusement de calculer 10 lignes pour que votre curseur consomme à partir d'un cache et faire d'autres choses en attendant.

HTH

47
AndreasT

Un curseur est un outil qui vous permet d'itérer les enregistrements d'un ensemble. Il a des concepts de ordre et enregistrement courant.

Généralement, SQL fonctionne avec des multisets: ce sont des ensembles d'enregistrements pouvant se répéter dans un ordre donné, pris dans leur ensemble.

Dites, cette requête:

SELECT  *
FROM    a
JOIN    b
ON      b.a = a.id

, fonctionne sur les multisets a et b.

Rien dans cette requête ne fait d'hypothèses sur l'ordre des enregistrements, comment ils sont stockés, dans quel ordre ils doivent être consultés, etc.

Cela permet d'abstraire les détails d'implémentation et de laisser le système essayer de choisir le meilleur algorithme possible pour exécuter cette requête.

Cependant, après avoir transformé toutes vos données, vous devrez finalement accéder aux enregistrements de manière ordonnée et un par un.

Vous ne vous souciez pas de la façon dont les entrées d'un répertoire sont stockées sur un disque dur, mais une imprimante nécessite qu'elles soient introduites dans l'ordre alphabétique; et les balises de mise en forme doivent être appliquées à chaque enregistrement individuellement.

C'est exactement là que les curseurs entrent en jeu. Chaque fois que vous traitez un jeu de résultats côté client, vous utilisez un curseur. Vous n'obtenez pas de mégaoctets de données non triées du serveur: vous obtenez simplement une petite variable: un descripteur d'ensemble de résultats, et écrivez simplement quelque chose comme ceci:

while (!rs.EOF) {
   process(rs);
   rs.moveNext();
}

C'est le curseur qui implémente tout cela pour vous.

Cela concerne bien sûr l'interaction base de données-client.

Quant à la base de données elle-même: à l'intérieur la base de données, vous avez rarement besoin des curseurs, car, comme je l'ai dit ci-dessus, presque toutes les transformations de données peuvent être implémentées en utilisant des opérations d'ensemble plus efficacement.

Cependant, il existe des exceptions:

  • Opérations analytiques dans SQL Server sont très mal implémentés. Une somme cumulée, par exemple, pourrait être calculée beaucoup plus efficacement avec un curseur que l'utilisation des opérations basées sur un ensemble
  • Traitement des données en morceaux . Dans certains cas, une opération basée sur un ensemble doit être appliquée séquentiellement à une portion d'un ensemble et les résultats de chaque bloc doivent être validés indépendamment. Bien qu'il soit toujours possible de le faire en utilisant des opérations basées sur un ensemble, un curseur est souvent un moyen plus préféré de le faire.
  • Récursion dans les systèmes qui ne le supportent pas nativement.

Vous pouvez également trouver cet article intéressant à lire:

27
Quassnoi

À l'aide d'un curseur, il est possible de lire séquentiellement un ensemble de données, par programmation, afin qu'il se comporte de la même manière que l'accès aux fichiers conventionnel, plutôt que la caractéristique de comportement basée sur un ensemble de SQL.

Il y a quelques situations où cela peut être utile:

  1. Où il est nécessaire de simuler un comportement d'accès aux enregistrements basé sur des fichiers - par exemple, lorsqu'une base de données relationnelle est utilisée comme mécanisme de stockage de données pour un morceau de code qui a été précédemment écrit pour utiliser des fichiers indexés pour le stockage de données.

  2. Lorsqu'il est nécessaire de traiter les données de manière séquentielle - un exemple simple pourrait être de calculer un solde total cumulé pour un client spécifique. (Un certain nombre de bases de données relationnelles, telles qu'Oracle et SQLServer, ont désormais des extensions analytiques pour SQL qui devraient considérablement réduire le besoin de cela.)

Inévitablement, wikipedia a plus: http://en.wikipedia.org/wiki/Database_cursor

3
user359040

Parfois, une logique basée sur un ensemble peut devenir assez complexe et opaque. Dans ces cas et si les performances ne sont pas un problème, un curseur côté serveur peut être utilisé pour remplacer la logique relationnelle par une logique procédurale plus gérable et familière (pour un penseur non relationnel), ce qui facilite la maintenance.

1
Clodoaldo Neto

Avec le curseur, vous accédez à une ligne à la fois. Il est donc bon de l'utiliser lorsque vous souhaitez manipuler avec beaucoup de lignes mais avec une seule à la fois.

On m'a dit lors de mes cours, la raison d'utiliser le curseur est que vous voulez accéder à plus de lignes que vous ne pouvez en contenir - vous ne pouvez donc pas simplement obtenir toutes les lignes dans une collection, puis la parcourir.

1
Hurda