gooderp18绿色标准版
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

178 行
9.3KB

  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>40.7. Rules Versus Triggers</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets V1.79.1" /><link rel="prev" href="rules-status.html" title="40.6. Rules and Command Status" /><link rel="next" href="xplang.html" title="Chapter 41. Procedural Languages" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">40.7. Rules Versus Triggers</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="rules-status.html" title="40.6. Rules and Command Status">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="rules.html" title="Chapter 40. The Rule System">Up</a></td><th width="60%" align="center">Chapter 40. The Rule System</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="xplang.html" title="Chapter 41. Procedural Languages">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="RULES-TRIGGERS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">40.7. Rules Versus Triggers</h2></div></div></div><a id="id-1.8.6.12.2" class="indexterm"></a><a id="id-1.8.6.12.3" class="indexterm"></a><p>
  3. Many things that can be done using triggers can also be
  4. implemented using the <span class="productname">PostgreSQL</span>
  5. rule system. One of the things that cannot be implemented by
  6. rules are some kinds of constraints, especially foreign keys. It is possible
  7. to place a qualified rule that rewrites a command to <code class="literal">NOTHING</code>
  8. if the value of a column does not appear in another table.
  9. But then the data is silently thrown away and that's
  10. not a good idea. If checks for valid values are required,
  11. and in the case of an invalid value an error message should
  12. be generated, it must be done by a trigger.
  13. </p><p>
  14. In this chapter, we focused on using rules to update views. All of
  15. the update rule examples in this chapter can also be implemented
  16. using <code class="literal">INSTEAD OF</code> triggers on the views. Writing such
  17. triggers is often easier than writing rules, particularly if complex
  18. logic is required to perform the update.
  19. </p><p>
  20. For the things that can be implemented by both, which is best
  21. depends on the usage of the database.
  22. A trigger is fired once for each affected row. A rule modifies
  23. the query or generates an additional query. So if many
  24. rows are affected in one statement, a rule issuing one extra
  25. command is likely to be faster than a trigger that is
  26. called for every single row and must re-determine what to do
  27. many times. However, the trigger approach is conceptually far
  28. simpler than the rule approach, and is easier for novices to get right.
  29. </p><p>
  30. Here we show an example of how the choice of rules versus triggers
  31. plays out in one situation. There are two tables:
  32. </p><pre class="programlisting">
  33. CREATE TABLE computer (
  34. hostname text, -- indexed
  35. manufacturer text -- indexed
  36. );
  37. CREATE TABLE software (
  38. software text, -- indexed
  39. hostname text -- indexed
  40. );
  41. </pre><p>
  42. Both tables have many thousands of rows and the indexes on
  43. <code class="structfield">hostname</code> are unique. The rule or trigger should
  44. implement a constraint that deletes rows from <code class="literal">software</code>
  45. that reference a deleted computer. The trigger would use this command:
  46. </p><pre class="programlisting">
  47. DELETE FROM software WHERE hostname = $1;
  48. </pre><p>
  49. Since the trigger is called for each individual row deleted from
  50. <code class="literal">computer</code>, it can prepare and save the plan for this
  51. command and pass the <code class="structfield">hostname</code> value in the
  52. parameter. The rule would be written as:
  53. </p><pre class="programlisting">
  54. CREATE RULE computer_del AS ON DELETE TO computer
  55. DO DELETE FROM software WHERE hostname = OLD.hostname;
  56. </pre><p>
  57. </p><p>
  58. Now we look at different types of deletes. In the case of a:
  59. </p><pre class="programlisting">
  60. DELETE FROM computer WHERE hostname = 'mypc.local.net';
  61. </pre><p>
  62. the table <code class="literal">computer</code> is scanned by index (fast), and the
  63. command issued by the trigger would also use an index scan (also fast).
  64. The extra command from the rule would be:
  65. </p><pre class="programlisting">
  66. DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
  67. AND software.hostname = computer.hostname;
  68. </pre><p>
  69. Since there are appropriate indexes set up, the planner
  70. will create a plan of
  71. </p><pre class="literallayout">
  72. Nestloop
  73. -&gt; Index Scan using comp_hostidx on computer
  74. -&gt; Index Scan using soft_hostidx on software
  75. </pre><p>
  76. So there would be not that much difference in speed between
  77. the trigger and the rule implementation.
  78. </p><p>
  79. With the next delete we want to get rid of all the 2000 computers
  80. where the <code class="structfield">hostname</code> starts with
  81. <code class="literal">old</code>. There are two possible commands to do that. One
  82. is:
  83. </p><pre class="programlisting">
  84. DELETE FROM computer WHERE hostname &gt;= 'old'
  85. AND hostname &lt; 'ole'
  86. </pre><p>
  87. The command added by the rule will be:
  88. </p><pre class="programlisting">
  89. DELETE FROM software WHERE computer.hostname &gt;= 'old' AND computer.hostname &lt; 'ole'
  90. AND software.hostname = computer.hostname;
  91. </pre><p>
  92. with the plan
  93. </p><pre class="literallayout">
  94. Hash Join
  95. -&gt; Seq Scan on software
  96. -&gt; Hash
  97. -&gt; Index Scan using comp_hostidx on computer
  98. </pre><p>
  99. The other possible command is:
  100. </p><pre class="programlisting">
  101. DELETE FROM computer WHERE hostname ~ '^old';
  102. </pre><p>
  103. which results in the following executing plan for the command
  104. added by the rule:
  105. </p><pre class="literallayout">
  106. Nestloop
  107. -&gt; Index Scan using comp_hostidx on computer
  108. -&gt; Index Scan using soft_hostidx on software
  109. </pre><p>
  110. This shows, that the planner does not realize that the
  111. qualification for <code class="structfield">hostname</code> in
  112. <code class="literal">computer</code> could also be used for an index scan on
  113. <code class="literal">software</code> when there are multiple qualification
  114. expressions combined with <code class="literal">AND</code>, which is what it does
  115. in the regular-expression version of the command. The trigger will
  116. get invoked once for each of the 2000 old computers that have to be
  117. deleted, and that will result in one index scan over
  118. <code class="literal">computer</code> and 2000 index scans over
  119. <code class="literal">software</code>. The rule implementation will do it with two
  120. commands that use indexes. And it depends on the overall size of
  121. the table <code class="literal">software</code> whether the rule will still be faster in the
  122. sequential scan situation. 2000 command executions from the trigger over the SPI
  123. manager take some time, even if all the index blocks will soon be in the cache.
  124. </p><p>
  125. The last command we look at is:
  126. </p><pre class="programlisting">
  127. DELETE FROM computer WHERE manufacturer = 'bim';
  128. </pre><p>
  129. Again this could result in many rows to be deleted from
  130. <code class="literal">computer</code>. So the trigger will again run many commands
  131. through the executor. The command generated by the rule will be:
  132. </p><pre class="programlisting">
  133. DELETE FROM software WHERE computer.manufacturer = 'bim'
  134. AND software.hostname = computer.hostname;
  135. </pre><p>
  136. The plan for that command will again be the nested loop over two
  137. index scans, only using a different index on <code class="literal">computer</code>:
  138. </p><pre class="programlisting">
  139. Nestloop
  140. -&gt; Index Scan using comp_manufidx on computer
  141. -&gt; Index Scan using soft_hostidx on software
  142. </pre><p>
  143. In any of these cases, the extra commands from the rule system
  144. will be more or less independent from the number of affected rows
  145. in a command.
  146. </p><p>
  147. The summary is, rules will only be significantly slower than
  148. triggers if their actions result in large and badly qualified
  149. joins, a situation where the planner fails.
  150. </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="rules-status.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="rules.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="xplang.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">40.6. Rules and Command Status </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 41. Procedural Languages</td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1