バージョンごとのドキュメント一覧

41.7. ルール対トリガ #

<title>Rules Versus Triggers</title>

Many things that can be done using triggers can also be implemented using the <productname>PostgreSQL</productname> rule system. One of the things that cannot be implemented by rules are some kinds of constraints, especially foreign keys. It is possible to place a qualified rule that rewrites a command to <literal>NOTHING</literal> if the value of a column does not appear in another table. But then the data is silently thrown away and that's not a good idea. If checks for valid values are required, and in the case of an invalid value an error message should be generated, it must be done by a trigger. トリガによって行われる多くの操作はPostgreSQLのルールシステムで実装可能です。 ルールで実装できないものの1つはある種の制約、特に外部キーに関してです。 もし他のテーブルに列の値がなかった場合、条件ルールでコマンドをNOTHINGに書き換えてしまうことも可能ですが、これではデータがだまって消去されてしまい、良いアイディアとは言えません。 有効な値かどうかのチェックが必要で、無効な値についてはエラーメッセージを表示する必要があるなら、このことは今のところトリガを使って行わなければなりません。

In this chapter, we focused on using rules to update views. All of the update rule examples in this chapter can also be implemented using <literal>INSTEAD OF</literal> triggers on the views. Writing such triggers is often easier than writing rules, particularly if complex logic is required to perform the update. この章ではビューを更新するのにルールを使うことに焦点を当ててきました。 この章の更新ルールの例はすべてビューのINSTEAD OFトリガを使っても実装できます。 特に更新を実行するのに複雑な論理が要求される場合には、そのようなトリガを書くことはしばしばルールを書くよりも簡単です。

For the things that can be implemented by both, which is best depends on the usage of the database. A trigger is fired once for each affected row. A rule modifies the query or generates an additional query. So if many rows are affected in one statement, a rule issuing one extra command is likely to be faster than a trigger that is called for every single row and must re-determine what to do many times. However, the trigger approach is conceptually far simpler than the rule approach, and is easier for novices to get right. どちらでも実装できる事項に関してどちらがベストかはデータベースの使用方法によります。 トリガは各行に対して一度起動します。 ルールは問い合わせを修正するか追加の問い合わせを生成します。 ですから、1つの文が多くの行に影響を与える場合、1つの行を処理する度に呼び出され、何をするかを何度も再決定しなければならないトリガよりも、追加の問い合わせを1つ発行するルールの方がほとんどの場合高速になります。 しかし、トリガ方式は概念的にルールシステムよりかなり単純であり、初心者は簡単に正しく扱うことができます。

Here we show an example of how the choice of rules versus triggers plays out in one situation. There are two tables: ここで、ある状況下でルールとトリガのどちらを選択するかを示す例を挙げます。 例えば、2つのテーブルがあるとします。


CREATE TABLE computer (
    hostname        text,    &#45;- indexed
    manufacturer    text     &#45;- indexed
);

CREATE TABLE computer (
    hostname        text,    -- インデックスあり
    manufacturer    text     -- インデックスあり
);


CREATE TABLE software (
    software        text,    &#45;- indexed
    hostname        text     &#45;- indexed
);

CREATE TABLE software (
    software        text,    -- インデックスあり
    hostname        text     -- インデックスあり
);

Both tables have many thousands of rows and the indexes on <structfield>hostname</structfield> are unique. The rule or trigger should implement a constraint that deletes rows from <literal>software</literal> that reference a deleted computer. The trigger would use this command: 2つのテーブルにはともに数千の行があって、hostname上のインデックスは一意です。 ルール/トリガは削除されたホストを参照する、softwareの行を削除する制限を実装しなければなりません。 トリガの場合は以下のコマンドを使用します。

DELETE FROM software WHERE hostname = $1;

Since the trigger is called for each individual row deleted from <literal>computer</literal>, it can prepare and save the plan for this command and pass the <structfield>hostname</structfield> value in the parameter. The rule would be written as: computerから削除された行1つひとつに対してこのトリガが呼び出されますので、このコマンドの準備を行い、計画を保存し、パラメータとしてhostnameを渡すことができます。 ルールの場合は以下のように作成されます。

CREATE RULE computer_del AS ON DELETE TO computer
    DO DELETE FROM software WHERE hostname = OLD.hostname;

Now we look at different types of deletes. In the case of a: ここで別の類の削除を考えてみましょう。

DELETE FROM computer WHERE hostname = 'mypc.local.net';

the table <literal>computer</literal> is scanned by index (fast), and the command issued by the trigger would also use an index scan (also fast). The extra command from the rule would be: 上のような場合では、computerはインデックスにより(高速に)スキャンされます。 トリガによってこのコマンドが発行された場合もインデックススキャンが使用されます(高速です)。 ルールによる追加コマンドは以下のようになります。

DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
                       AND software.hostname = computer.hostname;

Since there are appropriate indexes set up, the planner will create a plan of 適切なインデックスが設定されていますので、プランナは以下の計画を作成します。

Nestloop
  ->  Index Scan using comp_hostidx on computer
  ->  Index Scan using soft_hostidx on software

So there would be not that much difference in speed between the trigger and the rule implementation. ですので、トリガとルールの実装間での速度差はあまりありません。

With the next delete we want to get rid of all the 2000 computers where the <structfield>hostname</structfield> starts with <literal>old</literal>. There are two possible commands to do that. One is: 次の削除処理ではhostnameoldで始まる2,000台全てのcomputerを削除しようと思います。 方法として2つの有効な問い合わせがあって、1つは以下のようなものです。

DELETE FROM computer WHERE hostname >= 'old'
                       AND hostname <  'ole'

The command added by the rule will be: ルールによって追加されるコマンドは以下のようになります。

DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole'
                       AND software.hostname = computer.hostname;

with the plan これに対する計画は以下のようになります。

Hash Join
  ->  Seq Scan on software
  ->  Hash
    ->  Index Scan using comp_hostidx on computer

The other possible command is: もう1つのコマンドは以下のようなものです。

DELETE FROM computer WHERE hostname ~ '^old';

which results in the following executing plan for the command added by the rule: これにより、ルールによって追加されるコマンド用の実行計画は以下のようになります。

Nestloop
  ->  Index Scan using comp_hostidx on computer
  ->  Index Scan using soft_hostidx on software

This shows, that the planner does not realize that the qualification for <structfield>hostname</structfield> in <literal>computer</literal> could also be used for an index scan on <literal>software</literal> when there are multiple qualification expressions combined with <literal>AND</literal>, which is what it does in the regular-expression version of the command. The trigger will get invoked once for each of the 2000 old computers that have to be deleted, and that will result in one index scan over <literal>computer</literal> and 2000 index scans over <literal>software</literal>. The rule implementation will do it with two commands that use indexes. And it depends on the overall size of the table <literal>software</literal> whether the rule will still be faster in the sequential scan situation. 2000 command executions from the trigger over the SPI manager take some time, even if all the index blocks will soon be in the cache. これが示していることは、ANDで結合された複数の検索条件が存在する場合、プランナは正規表現版のコマンドでは行っていることですが、computer上のhostnameに対する検索条件をsoftware上のインデックススキャンにも同様に使用できることを理解しないということです。 トリガは削除されるべき2,000台の旧式コンピュータのそれぞれについて1回呼び出され、結果computer上で1回のインデックススキャンとsoftware上で2,000回のインデックススキャンが行われます。 ルールによる実装ではインデックスを使用する2つの問い合わせによって実行されます。 シーケンシャルスキャンの場合でもルールがより速いかどうかはsoftwareテーブルの大きさに依存します。 参照する全てのインデックスブロックがすぐにキャッシュに現れるとしても、トリガによるSPIマネージャ経由の2,000回のコマンドの実行には時間を要します。

The last command we look at is: 最後のコマンドを見てみましょう。

DELETE FROM computer WHERE manufacturer = 'bim';

Again this could result in many rows to be deleted from <literal>computer</literal>. So the trigger will again run many commands through the executor. The command generated by the rule will be: この文でもcomputerから多くの行が削除される結果となります。 ですので、ここでもトリガはエグゼキュータを通して多くのコマンドを実行することになります。 ルールで作成されるコマンドは以下のようなものです。

DELETE FROM software WHERE computer.manufacturer = 'bim'
                       AND software.hostname = computer.hostname;

The plan for that command will again be the nested loop over two index scans, only using a different index on <literal>computer</literal>: このコマンド用の計画もまた前回同様2つのインデックススキャンのネステッドループとなります。 computerの別のインデックスを使用する点のみが異なります。

Nestloop
  ->  Index Scan using comp_manufidx on computer
  ->  Index Scan using soft_hostidx on software

In any of these cases, the extra commands from the rule system will be more or less independent from the number of affected rows in a command. いずれの場合においても、ルールシステムが生成する追加コマンドは影響を受ける行数からは多かれ少なかれ独立しています。

The summary is, rules will only be significantly slower than triggers if their actions result in large and badly qualified joins, a situation where the planner fails. まとめると、問い合わせ結果が大きく、プランナがうまく結合条件を設定できないような状況下でのみルールはトリガに比べて明らかに遅くなります。