触发器与非规范化存储过程的优缺点

Posted

技术标签:

【中文标题】触发器与非规范化存储过程的优缺点【英文标题】:Pros and Cons of Triggers vs. Stored Procedures for Denormalization 【发布时间】:2011-01-06 12:43:43 【问题描述】:

当涉及到对事务数据库中的数据进行非规范化以提高性能时,有(至少)三种不同的方法:

    通过存储过程推送更新,该存储过程同时更新规范化事务数据和非规范化报告/分析数据;

    在更新辅助表的事务表上实现触发器;这几乎是维护历史时所采用的路线;

    将处理推迟到夜间批处理,可能会在数据集市/仓库中执行 ETL。

出于这个问题的目的,我们假设选项 #3 不可行,因为域要求非规范化数据始终与规范化数据保持一致。我经常处理的分层聚合就是一个例子。

我已经相当多地使用了前两种方法,最近我一直倾向于基于触发器的方法,但我想知道是否有任何我尚未发现的“陷阱”,并认为值得提出这个问题,以便在将来做出长期决策时牢记一些想法。

那么根据您的经验,对于维护实时非规范化数据的特定目的,这两种工具的优缺点是什么?在什么情况下你会选择其中一种,为什么?

(附注:请不要回答“触发器太复杂”或“所有更新都应始终通过存储过程”之类的答案 - 使其适合问题的上下文。)

【问题讨论】:

使用物化视图进行非规范化不是更好吗? @Enrique:物化视图不是灵丹妙药;有各种视图您实际上无法实现(甚至无法通过模式绑定创建),即使您可以,它们也具有与触发器大致相同的性能特征。 【参考方案1】:

触发器是自动的副作用,当你想做某事但由于触发器的副作用而不能做时,几乎肯定会咬你。主要是让你的系统参与在与其他外部系统的一些 XA 事务中。触发器使这成为不可能。此外,它是副作用逻辑,只能通过再次执行 Trigger 激活器来激活。如果你想在仓库中重新创建数据,你不能只运行一些程序并重新创建它,你必须执行所有会触发触发器的活动,这是一场噩梦。 INSERTS、UPDATES 和 DELETES 应该是幂等且正交的。触发器不必要地使工作流程复杂化,即使您认为它们正在简化它们,但事实并非如此。

【讨论】:

我一直在争论是否使用存储过程和触发器。我可以快速决定不使用存储过程,但在使用触发器时遇到了麻烦。你为我解决了这个问题:它们使工作流程复杂化的原因对我来说已经足够了。 :-) 这是我对触发器的最大担忧之一。基于副作用的逻辑仅对异步、非原子行为和 UI 才真正有意义。【参考方案2】:

这取决于您的业务需求以及您的数据库的使用方式。例如,假设有许多应用程序和许多影响表的导入(我们有数百个可以影响表的事物)。假设有时还需要编写从 SSMS 运行的查询(是的,即使在 prod 上也是如此)来执行诸如将所有价格更新 10% 之类的事情。如果你做这些类型的事情,那么存储过程是不切实际的,你永远不会有所有可能的方式来影响所覆盖的数据库。

如果此数据更改对于数据完整性是必要的,或者许多应用程序或进程(导入、SQL Server 作业等)会影响数据,则它属于触发器。

如果只是有时需要更改数据,或者您可以完全控制如何仅从一个应用程序更改数据,那么存储过程就可以了。

【讨论】:

【参考方案3】:

当您在一个表上使用多个更新路径时,触发器很有用。

我们使用存储过程并且至少有大约 4 个路径(添加、更新、停用、复制)

无论我们执行什么操作或影响多少行,都可以更轻松地处理我们刚刚在触发器中插入/更新的数据。

我觉得存储过程仅适用于单个更新路径:除非您想重复代码...

现在,触发器中的 TRY/CATCH 意味着正确、可预测的错误处理:SQL Server 2000 和更早版本上的触发器导致错误/回滚时批处理中止,这并不理想(至少可以这么说!)。所以,无论如何,触发器现在更可靠了。

【讨论】:

我很好奇 - 如果触发器中发生错误,您为什么不想中止?是否存在可以让触发器的工作未完成(或半完成)的情况? 仅当您想让您的系统/数据处于不一致状态时。背景文章中的一些信息在这里:sommarskog.se/error_handling_2005.html

以上是关于触发器与非规范化存储过程的优缺点的主要内容,如果未能解决你的问题,请参考以下文章

MySQL触发器定义及其优缺点

历史表的优点、缺点和陷阱 - 使用触发器、存储过程或在应用程序级别 [关闭]

对比索引视图游标存储过程和触发器

数据库术语之存储过程(Stored Procedure)

MySQL-存储过程与触发器

轻松掌握MySQL数据库存储过程和触发器原理