制定通知计划

若要有效地使用查询通知,应该考虑应用程序是否可以通过查询通知受益,应用程序使用的查询是否支持通知,以及应用程序订阅和接收通知将使用的策略。

如果查询中的数据更改相对较少,或数据更改时应用程序不要求立即更新,或查询满足为通知创建查询中所述的要求和限制,那么使用查询通知可提供一种便利方法来减少往返数据库的次数。许多基于 Web 的应用程序都满足这些条件,并且这些应用程序可以利用查询通知。

并非每种情况都可以通过查询通知受益。当应用程序经常读取数据库中的数据,但是相对较少进行数据更新时,查询通知是很有用的。例如,查看联机目录应用程序比更新目录更加频繁。但是,对于在线购物车,可能会经常更新特定的内容,这样查询通知的作用不大。

当应用程序执行的查询共享通用结构并且只有参数值不同时,查询通知将更加有效。例如:

SELECT ProductNumber, Name FROM Production.Product WHERE ListPrice < 300
SELECT ProductNumber, Name FROM Production.Product WHERE ListPrice < 500

在这种情况下,这两个通知的查询通知订阅共享同一个内部模板,并要求在 SQL Server 中的开销小于带有不同查询结构的两个通知的开销。但是,请注意保留查询中的参数。即使查询共享一个模板,添加 ListPrice 为 350 的项将在第二个查询上导致通知,而不是在第一个查询上。

当查询通知在表上处于活动状态时,更新该表的开销会更大。数据库引擎执行额外的工作以检查订阅并根据需要生成通知。重用内部模板有助于最小化每个订阅的开销。因此,应该仅将查询通知用于提交带有相似结构查询的应用程序。提交带有不同结构查询的应用程序不应使用查询通知。

例如,显示给定价格范围中的目录项的应用程序提交带有相同结构的查询。在这种情况下,数据库引擎可以重用每个查询的内部模板,并且查询通知可以提高性能。但是,允许生成即席报表的应用程序提交带有不同结构的查询。在这种情况下,应用程序不应使用查询通知。

只要至少有一个注册的订阅使用内部模板,数据库引擎就会维护此内部模板。数据库引擎对特定表的不同内部模板的数量有限制。达到此限制后,数据库引擎将不再注册会导致创建新模板的订阅。相反的,数据库引擎立即生成一条订阅消息,指明不能注册订阅。

计划高效的查询通知策略

在通知的总数不多并且应用程序不要求在数据发生变化时立即发出通知以便作为响应的情况下,查询通知通常表现非常出色。典型的 Web 层缓存失效通知方案适合于此模型,并且往往是对使用查询通知的很好的应用。在以下情况下时,查询通知可能不是最佳应用选择:必须以次秒级响应时间接收通知时、网络基础结构并不快速且可靠时或者通知量非常大时。

在使用查询通知时,按照在部署后您的应用程序将在其中操作的环境和规模测试并优化您的应用程序。考虑到具有最高预期负载的真实用例情况,并且对有可能发生的突发性大量使用的情形事先周密计划。

如果您在需要可靠的次秒级查询通知的情况下使用查询通知,则适用于生成任何高性能 OLTP 应用程序的相同技术也适用于您的查询通知应用程序。

  • 请确保您的应用程序未持有长于几分之一秒的锁。例如,不要在具有不可靠性能的网络上从客户端运行多语句事务。

  • 找到并消除您的用户数据表中的热点。

  • 对于对其设置了查询通知的相关用户表的每个更新,通常按顺序扫描查询通知内部表。如果在查询通知内部表上持有的表级别锁可能会成为瓶颈,则考虑将具有查询通知的用户表划分为若干单独的表,以便减少必须为每个数据更改评估的可能通知的数目。

如果您的通知请求的正常生命周期较短,则考虑将显著少于默认值 5 天(例如 1 分钟)的超时值用于 SqlDependency 构造函数。这可以大幅减少内部查询通知表中的行数。而减少行数又可以缩短处理这些表所需的时间,并且可以减少针对这些表的锁争用。

查询通知的替代方法

对于具有高数据更新率和许多待定通知请求的环境中的数据更改,如果您需要快速且高度可预测的通知响应时间,则考虑采用替代解决方案,例如以下解决方案之一:

  • 对要监视的表创建一个 AFTER UPDATE 触发器,其操作使用 SQL Server Service Broker 将消息发送到需要通知的实体。(可通过若干方式对此进行设计,例如向感兴趣的表添加一列,指示必须通知更改的实体;或者将主表与辅助表相联接,辅助表中包含与要求通知的实体有关的信息。)

  • 使用不依赖于查询通知的自定义应用层解决方案。例如,将通知配置为完全从某一中间件应用程序发生,该应用程序维护在主内存对象的集合中监视的数据。您的应用程序可以在修改某一对象时生成通知,只要满足您的通知条件。

  • 使用 Windows Server App Fabric Cache,它基于内存中对象缓存和您向对象注册的回调函数,支持更改通知机制。

请参阅

概念