PostgreSQL 规则有啥用?
Posted
技术标签:
【中文标题】PostgreSQL 规则有啥用?【英文标题】:What are PostgreSQL RULEs good for?PostgreSQL 规则有什么用? 【发布时间】:2011-08-19 03:28:52 【问题描述】:问题
我经常看到它说rules should be avoided and triggers used instead。我可以看到规则系统的危险,但规则肯定有有效的用途,对吧?它们是什么?
我问这个是出于普遍的兴趣;我对数据库不是很熟悉。
可能是有效用途的示例
例如,过去我需要锁定某些数据,所以我做了这样的事情:
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
那么如果我想编辑受保护的数据:
START TRANSACTION;
ALTER TABLE exampletable DISABLE RULE protect_data;
-- edit data as I like
ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;
我同意这是 hacky,但在这种情况下,我无法更改访问数据库的应用程序(甚至无法对其抛出错误)。所以 奖励积分 可以找到原因对规则系统的危险/无效使用,但不是糟糕的设计。
【问题讨论】:
无效使用。应该用触发器来完成。 【参考方案1】:RULES 的一个用例是可更新的视图(尽管在 9.1 中发生了变化,因为该版本为视图引入了 INSTEAD OF 触发器)
另一个很好的解释可以在手册中找到:
对于两者都可以实现的东西,最好取决于数据库的使用情况。任何受影响的行都会触发一次触发器。规则操纵查询或生成附加查询。因此,如果一条语句中影响了许多行,则发出一个额外命令的规则可能比为每一行调用并且必须多次执行其操作的触发器更快。不过,触发方式在概念上远比规则方式简单,新手也更容易上手。
(取自:http://www.postgresql.org/docs/current/static/rules-triggers.html)
【讨论】:
是否有任何理由使用规则而不是语句级触发器?【参考方案2】:这里显示了一些规则问题:http://www.depesz.com/index.php/2010/06/15/to-rule-or-not-to-rule-that-is-the-question/(例如,如果一个 random() 包含在查询中,它可能会被执行两次并返回不同的值)。
规则的最大缺点是人们不理解它们。
例如,有人可能认为有规则:
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
将意味着如果我发出:
update exampletable set whatever = whatever + 1 where type = 'protected'
不会运行任何查询。这不是真的。查询将运行,但将在修改后的版本中运行 - 添加条件。
更重要的是——规则打破了非常有用的东西,那就是返回子句:
$ update exampletable set whatever = whatever + 1 where type = 'normal' returning *;
ERROR: cannot perform UPDATE RETURNING on relation "exampletable"
HINT: You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.
为了包装它——如果你真的、真的、肯定地必须使用可写视图,并且你使用的是 9.1 之前的 PostgreSQL——你可能有一个使用规则的正当理由。
在所有其他情况下 - 即使您没有立即看到它,您很可能会在脚上开枪。
【讨论】:
+1 打破RETURNING
确实是避免规则的一个很好的理由,而且我没有想到。我的示例可以看作是一个可写视图,所以我想你的总结是有道理的。【参考方案3】:
在处理 volatile 函数时,我在规则方面有过一些痛苦的经历(如果没记错的话,depesz 的博客文章会重点介绍其中的一些)。
由于 fkey 触发器被触发的时间,我在使用它们时也破坏了参照完整性:
CREATE OR REPLACE RULE protected_example AS
ON DELETE TO example
WHERE OLD.protected
DO INSTEAD NOTHING;
... 然后添加另一个表,并使用删除级联外键示例引用该表。然后,从那个表中删除 *……然后惊恐地退缩。
我将上述问题报告为错误,该错误被视为功能/必要的边缘情况而被驳回。仅仅几个月后,我才明白为什么会这样,即 fkey 触发器完成了它的工作,然后规则开始执行它自己的工作,但是 fkey 触发器不会因为性能原因检查它的工作是否正确完成.
我仍然使用规则的实际用例是,当 BEFORE
触发器预操作数据时(SQL 标准说不允许,但 Postgres 会很乐意)可能导致预操作受影响的行和从而改变他们的 ctid(即它被更新了两次,或者没有被删除,因为更新使删除无效)。
这会导致 Postgres 返回不正确的受影响行数,这没什么大不了的,除非您在发出后续语句之前监控该数字。
在这种情况下,我发现使用一个或两个策略性放置的规则可以允许先发制人地执行有问题的语句,从而导致 Postgres 返回正确数量的受影响的行。
【讨论】:
【参考方案4】:这个怎么样:你有一个表需要变成一个视图。为了支持插入到所述表中的遗留应用程序,创建了一个规则,将“插入”映射到新视图到基础表。
【讨论】:
以上是关于PostgreSQL 规则有啥用?的主要内容,如果未能解决你的问题,请参考以下文章
B-Tree 和 GiST 索引方法(在 PostgreSQL 中)有啥区别?