Cuáles son las limitaciones de SqlDependency

Estoy usando una tabla como una cola de mensajes y “registrándome” para buscar actualizaciones usando una SqlDependency. En todas partes que leo, la gente dice que vean las limitaciones pero que no digan específicamente lo que son. Por lo que he reunido, tendrás problemas cuando la tabla tenga una frecuencia de actualización muy alta, afortunadamente solo estoy viendo 10-20 valores por minuto como máximo.

¿Cuáles son las otras limitaciones / impacto en el SqlServer?

La lista más completa que puedo encontrar ( desde aquí ) es la siguiente:

  • Las columnas proyectadas en la statement SELECT deben declararse explícitamente, y los nombres de las tablas deben calificarse con nombres de dos partes. Tenga en cuenta que esto significa que todas las tablas a las que se hace referencia en la statement deben estar en la misma base de datos.
  • La instrucción no puede usar el asterisco ( ) o el nombre de la tabla. syntax para especificar columnas
  • La statement no puede usar columnas sin nombre ni nombres de columna duplicados.
  • La statement debe hacer referencia a una tabla base.
  • La statement no debe hacer referencia a tablas con columnas calculadas.
  • Las columnas proyectadas en la instrucción SELECT no pueden contener expresiones agregadas a menos que la instrucción use una expresión GROUP BY. Cuando se proporciona una expresión GROUP BY, la lista de selección puede contener las funciones agregadas COUNT_BIG () o SUM (). Sin embargo, SUM () no se puede especificar para una columna que admite nulos. La instrucción puede no especificar HAVING, CUBE o ROLLUP.
  • Una columna proyectada en la instrucción SELECT que se usa como expresión simple no debe aparecer más de una vez.
  • La statement no debe incluir operadores PIVOT o UNPIVOT.
  • La statement no debe incluir los operadores UNION, INTERSECT o EXCEPT.
  • La statement no debe hacer referencia a una vista.
  • La statement no debe contener ninguno de los siguientes: DISTINCT, COMPUTE o COMPUTE BY, o INTO.
  • La statement no debe hacer referencia a las variables globales del servidor (@@ variable_name).
  • La instrucción no debe hacer referencia a tablas derivadas, tablas temporales o variables de tabla.
  • La statement no debe hacer referencia a tablas o vistas de otras bases de datos o servidores.
  • La instrucción no debe contener subconsultas, combinaciones externas o autocombinaciones.
  • La instrucción no debe hacer referencia a los tipos de objetos grandes: texto, ntexto e imagen.
  • La instrucción no debe usar los predicados de texto completo CONTAINS o FREETEXT.
  • La instrucción no debe usar funciones de conjunto de filas, incluidos OPENROWSET y OPENQUERY.
  • La instrucción no debe usar ninguna de las siguientes funciones agregadas: AVG, COUNT (*), MAX, MIN, STDEV, STDEVP, VAR o VARP.
  • La statement no debe usar ninguna función no determinista, incluidas las funciones de clasificación y ventanas.
  • La instrucción no debe contener agregados definidos por el usuario.
  • La instrucción no debe hacer referencia a las tablas o vistas del sistema, incluidas las vistas de catálogo y las vistas de gestión dinámica.
  • La statement no debe incluir información FOR BROWSE.
  • La statement no debe hacer referencia a una cola.
  • La instrucción no debe contener sentencias condicionales que no pueden cambiar y no pueden devolver resultados (por ejemplo, WHERE 1 = 0).
  • La instrucción no puede especificar la sugerencia de locking de READPAST.
  • La statement no debe hacer referencia a ninguna COLA de Service Broker.
  • La statement no debe hacer referencia a sinónimos.
  • La statement no debe tener comparación o expresión basada en tipos de datos dobles / reales.
  • La statement no debe usar la expresión TOP.

Referencia (s) adicional (es):

  • Trabajando con notificaciones de consulta

Además de esto, para cualquier persona que esté pensando en usar SqlDependency para recibir notificaciones sobre cambios, he estado usando este enfoque en producción, y estoy encontrando problemas con él. Estoy investigando para ver si los problemas están relacionados con mi código, pero los principales problemas son:

  • Si activa varios cambios en sucesión rápida, no siempre obtiene el número equivalente de eventos que llegan al código. En mi código, si se insertan 2 registros nuevos uno después del otro, solo recibo una notificación (para la última).

  • No hay forma de saber el registro que se agregó. Por lo tanto, si agrega un nuevo registro y el código se activa para recibir la notificación, no hay forma de que el código conozca el ID de ese nuevo registro, por lo que debe consultarlo en la base de datos.

Pasé un día persiguiendo un problema con SQL Service Broker que no funciona, la causa raíz fue hacer referencia a la base de datos en el procedimiento almacenado.

Por ejemplo, esta select funciona bien en SQL Management Studio:

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

Sin embargo, esto es rechazado por SQL Service Broker porque estamos haciendo referencia a la base de datos en la instrucción select, y la callback desde SqlDependency vuelve con Invalid en SqlNotificationEventArgs e , consulte http://msdn.microsoft.com/en-us/library/ ms189308.aspx .

Alterar el SQL pasado a SqlDependency a la siguiente statement eliminó el error:

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

Actualizar

El ejemplo anterior es solo una de muchas, muchas limitaciones a la statement de SQL de la que depende SQL Service Broker. Para obtener una lista completa de limitaciones, consulte ¿Cuáles son las limitaciones de SqlDependency ?

¿La razón? La statement de SQL que utiliza SQL Service Broker se convierte, detrás de escena, en instrucciones para supervisar el Registro de Transacciones de SQL en busca de cambios en la base de datos. Esta monitorización se realiza en el núcleo de SQL Server, lo que lo hace extremadamente rápido cuando se trata de detectar cambios en la (s) tabla (s). Sin embargo, esta velocidad tiene un costo: no puede usar simplemente cualquier statement SQL, debe usar una que se pueda convertir en instrucciones para monitorear el Registro de transacciones SQL .

Tenga en cuenta que no puede usar una pista de nolock en el procedimiento almacenado o que la dependencia permanecerá inválida y, por lo tanto, cualquier caché que realice en ella re-consultará permanentemente la base de datos.

 with (NOLOCK) 

Esto no parece ser mencionado en la documentación (por lo que puedo decir)

Se requieren las siguientes opciones SET antes del script de procedimiento

 SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON 

Otros han argumentado que estas opciones SET también son necesarias, pero no creo que lo sean. Aunque es una buena idea establecerlo así de todos modos.

 SET CONCAT_NULL_YIELDS_NULL ON SET QUOTED_IDENTIFIER ON SET NUMERIC_ROUNDABORT OFF SET ARITHABORT ON 

Otro gran problema que tengo con esta tecnología es la necesidad de que la conexión del suscriptor tenga permisos de Crear procedimiento. La capa de servicio web de mi aplicación en el trabajo en este momento se ejecuta como un usuario restringido. Para configurar las notificaciones mediante SQLDependency, tendría que abrir ese usuario para crear procs. Suena como un buen paso en el camino de ser dueño.

Para superar estas limitaciones, puede intentar usar SqlTableDependency. Eche un vistazo a http://www.sqltabledependency.it