web-dev-qa-db-fra.com

Quelles sont les limites de SqlDependency

J'utilise une table comme file d'attente de messages et je m'inscris pour des mises à jour en utilisant une SqlDependency. Partout où je lis, les gens disent que faites attention aux limites de cela, mais ne dites pas précisément ce qu'ils sont. D'après ce que j'ai compris, vous aurez des problèmes lorsque la table a une fréquence de mise à jour très élevée, heureusement, je ne regarde que 10 à 20 valeurs par minute maximum.

Quelles sont les autres limitations/impacts sur le SqlServer?

40
fluf

La liste la plus complète que je puisse trouver ( d'ici ) est la suivante:

  • Les colonnes projetées dans l'instruction SELECT doivent être explicitement indiquées et les noms de table doivent être qualifiés avec des noms en deux parties. Notez que cela signifie que toutes les tables référencées dans l'instruction doivent se trouver dans la même base de données.
  • L'instruction ne peut pas utiliser la syntaxe astérisque () ou nom_table. pour spécifier les colonnes.
  • L'instruction ne peut pas utiliser de colonnes sans nom ni de noms de colonnes en double.
  • L'instruction doit faire référence à une table de base.
  • L'instruction ne doit pas référencer des tables avec des colonnes calculées.
  • Les colonnes projetées dans l'instruction SELECT ne peuvent pas contenir d'expressions d'agrégation, sauf si l'instruction utilise une expression GROUP BY. Lorsqu'une expression GROUP BY est fournie, la liste de sélection peut contenir les fonctions d'agrégation COUNT_BIG () ou SUM (). Cependant, SUM () peut ne pas être spécifié pour une colonne nullable. L'instruction ne peut pas spécifier HAVING, CUBE ou ROLLUP.
  • Une colonne projetée dans l'instruction SELECT utilisée comme expression simple ne doit pas apparaître plus d'une fois.
  • L'instruction ne doit pas inclure d'opérateurs PIVOT ou UNPIVOT.
  • L'instruction ne doit pas inclure les opérateurs UNION, INTERSECT ou EXCEPT.
  • L'instruction ne doit pas faire référence à une vue.
  • La déclaration ne doit contenir aucun des éléments suivants: DISTINCT, COMPUTE ou COMPUTE BY ou INTO.
  • L'instruction ne doit pas référencer les variables globales du serveur (@@ nom_variable).
  • L'instruction ne doit pas faire référence à des tables dérivées, des tables temporaires ou des variables de table.
  • L'instruction ne doit pas référencer des tables ou des vues d'autres bases de données ou serveurs.
  • L'instruction ne doit pas contenir de sous-requêtes, de jointures externes ou d'auto-jointures.
  • L'instruction ne doit pas référencer les types d'objets volumineux: texte, ntext et image.
  • L'instruction ne doit pas utiliser les prédicats de texte intégral CONTAINS ou FREETEXT.
  • L'instruction ne doit pas utiliser de fonctions d'ensemble de lignes, y compris OPENROWSET et OPENQUERY.
  • L'instruction ne doit utiliser aucune des fonctions d'agrégation suivantes: AVG, COUNT (*), MAX, MIN, STDEV, STDEVP, VAR ou VARP.
  • L'instruction ne doit utiliser aucune fonction non déterministe, y compris les fonctions de classement et de fenêtrage.
  • L'instruction ne doit pas contenir d'agrégats définis par l'utilisateur.
  • L'instruction ne doit pas référencer les tables ou les vues système, y compris les vues de catalogue et les vues de gestion dynamique.
  • La déclaration ne doit pas contenir d'informations FOR BROWSE.
  • L'instruction ne doit pas référencer une file d'attente.
  • L'instruction ne doit pas contenir d'instructions conditionnelles qui ne peuvent pas changer et ne peuvent pas renvoyer de résultats (par exemple, WHERE 1 = 0).
  • L'instruction ne peut pas spécifier d'indication de verrouillage READPAST.
  • La déclaration ne doit faire référence à aucun courtier de services QUEUE.
  • La déclaration ne doit pas faire référence à des synonymes.
  • L'instruction ne doit pas avoir de comparaison ou d'expression basée sur des types de données doubles/réels.
  • L'instruction ne doit pas utiliser l'expression TOP.

Référence (s) supplémentaire (s):

61
Smudge202

En plus de cela, pour quiconque envisage d'utiliser SqlDependency pour recevoir des notifications sur les modifications, j'ai utilisé cette approche en production et je rencontre des problèmes avec elle. J'y cherche pour voir si les problèmes sont liés à mon code, mais les principaux problèmes sont:

  • Si vous déclenchez plusieurs modifications en succession rapide, vous n'obtenez pas toujours le nombre équivalent d'événements transmis au code. Dans mon code, si 2 nouveaux enregistrements sont insérés l'un après l'autre, je ne reçois qu'une seule notification (pour la dernière).

  • Il n'y a aucun moyen de connaître l'enregistrement qui a été ajouté. Donc, si vous ajoutez un nouvel enregistrement et que le code se déclenche pour recevoir la notification, il n'y a aucun moyen dans le code de connaître l'ID de ce nouvel enregistrement, vous devez donc l'interroger dans la base de données.

12
Matt Roberts

J'ai passé une journée à rechercher un problème avec SQL Service Broker qui ne fonctionnait pas, la cause principale faisant référence à la base de données dans la procédure stockée.

Par exemple, cette select fonctionne correctement dans SQL Management Studio:

select [MyColumn] from [MyDatabase].[MySchema].[MyTable]

Cependant, cela est rejeté par SQL Service Broker car nous référençons la base de données dans l'instruction select et le rappel de SqlDependency revient avec Invalid dans SqlNotificationEventArgs e, voir http://msdn.Microsoft.com/en-us/library/ms189308.aspx .

La modification du SQL passé dans SqlDependency à l'instruction suivante a éliminé l'erreur:

select [MyColumn] from [MySchema].[MyTable]

Mise à jour

L'exemple ci-dessus n'est qu'une des nombreuses limitations de l'instruction SQL dont dépend SQL Service Broker. Pour une liste complète des limitations, voir Quelles sont les limitations de SqlDependency .

La raison? L'instruction SQL utilisée par SQL Service Broker est convertie, en arrière-plan, en instructions pour surveiller le SQL Transaction Log pour les modifications de la base de données. Cette surveillance est effectuée dans le cœur de SQL Server, ce qui le rend extrêmement rapide lorsqu'il s'agit de détecter les modifications apportées aux tables. Cependant, cette vitesse a un coût: vous ne pouvez pas utiliser n'importe quelle instruction SQL, vous devez en utiliser une qui peut être convertie en instructions pour surveiller le SQL Transaction Log .

9
Contango

Notez que vous ne pouvez pas utiliser d'indicateur nolock dans la procédure stockée ou que la dépendance restera constamment invalide et que tout cache que vous y effectuerez réinterrogera définitivement la base de données.

with (NOLOCK) 

Cela ne semble pas être mentionné dans la documentation (pour autant que je sache)

Les options SET suivantes sont requises avant le script de procédure

SET ANSI_NULLS ON
SET ANSI_PADDING ON  
SET ANSI_WARNINGS ON

D'autres ont fait valoir que ces options SET sont également nécessaires, mais je ne pense pas qu'elles le soient. C'est quand même une bonne idée de régler comme ça.

SET CONCAT_NULL_YIELDS_NULL ON 
SET QUOTED_IDENTIFIER ON 
SET NUMERIC_ROUNDABORT OFF 
SET ARITHABORT ON
5
David Bridge

Un autre gros problème que j'ai avec cette technologie: la nécessité pour la connexion d'abonné d'avoir des autorisations de procédure de création. La couche de service Web de mon application au travail fonctionne actuellement en tant qu'utilisateur restreint. Pour obtenir la configuration des notifications à l'aide de SQLDependency, je devrais ouvrir cet utilisateur pour créer des procs. Cela ressemble à une très bonne étape sur le chemin de l'acquisition.

3
Mike

Pour surmonter ces limitations, vous pouvez essayer d'utiliser SqlTableDependency. Jetez un œil sur www.sqltabledependency.it

2

Il utilise Service Broker. Par conséquent, cela ne fonctionnera pas sur les instances SQL Azure non gérées. Soyez donc prudent si vous utilisez SQL Azure ou si vous le pourriez.

https://docs.Microsoft.com/en-us/Azure/sql-database/sql-database-features

Courtier de service

Pris en charge par des bases de données uniques et des pools élastiques:

Non

Pris en charge par les instances gérées:

Oui, mais uniquement dans l'instance. Voir différences Service Broker

Donc, ce n'est probablement pas un bon choix, sauf si tous vos environnements peuvent l'utiliser!

0
Simon_Weaver