gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 line
8.9KB

  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.3. Materialized Views</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-views.html" title="40.2. Views and the Rule System" /><link rel="next" href="rules-update.html" title="40.4. Rules on INSERT, UPDATE, and DELETE" /></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.3. Materialized Views</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="rules-views.html" title="40.2. Views and the Rule System">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="rules-update.html" title="40.4. Rules on INSERT, UPDATE, and DELETE">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="RULES-MATERIALIZEDVIEWS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">40.3. Materialized Views</h2></div></div></div><a id="id-1.8.6.8.2" class="indexterm"></a><a id="id-1.8.6.8.3" class="indexterm"></a><a id="id-1.8.6.8.4" class="indexterm"></a><p>
  3. Materialized views in <span class="productname">PostgreSQL</span> use the
  4. rule system like views do, but persist the results in a table-like form.
  5. The main differences between:
  6. </p><pre class="programlisting">
  7. CREATE MATERIALIZED VIEW mymatview AS SELECT * FROM mytab;
  8. </pre><p>
  9. and:
  10. </p><pre class="programlisting">
  11. CREATE TABLE mymatview AS SELECT * FROM mytab;
  12. </pre><p>
  13. are that the materialized view cannot subsequently be directly updated
  14. and that the query used to create the materialized view is stored in
  15. exactly the same way that a view's query is stored, so that fresh data
  16. can be generated for the materialized view with:
  17. </p><pre class="programlisting">
  18. REFRESH MATERIALIZED VIEW mymatview;
  19. </pre><p>
  20. The information about a materialized view in the
  21. <span class="productname">PostgreSQL</span> system catalogs is exactly
  22. the same as it is for a table or view. So for the parser, a
  23. materialized view is a relation, just like a table or a view. When
  24. a materialized view is referenced in a query, the data is returned
  25. directly from the materialized view, like from a table; the rule is
  26. only used for populating the materialized view.
  27. </p><p>
  28. While access to the data stored in a materialized view is often much
  29. faster than accessing the underlying tables directly or through a view,
  30. the data is not always current; yet sometimes current data is not needed.
  31. Consider a table which records sales:
  32. </p><pre class="programlisting">
  33. CREATE TABLE invoice (
  34. invoice_no integer PRIMARY KEY,
  35. seller_no integer, -- ID of salesperson
  36. invoice_date date, -- date of sale
  37. invoice_amt numeric(13,2) -- amount of sale
  38. );
  39. </pre><p>
  40. If people want to be able to quickly graph historical sales data, they
  41. might want to summarize, and they may not care about the incomplete data
  42. for the current date:
  43. </p><pre class="programlisting">
  44. CREATE MATERIALIZED VIEW sales_summary AS
  45. SELECT
  46. seller_no,
  47. invoice_date,
  48. sum(invoice_amt)::numeric(13,2) as sales_amt
  49. FROM invoice
  50. WHERE invoice_date &lt; CURRENT_DATE
  51. GROUP BY
  52. seller_no,
  53. invoice_date
  54. ORDER BY
  55. seller_no,
  56. invoice_date;
  57. CREATE UNIQUE INDEX sales_summary_seller
  58. ON sales_summary (seller_no, invoice_date);
  59. </pre><p>
  60. This materialized view might be useful for displaying a graph in the
  61. dashboard created for salespeople. A job could be scheduled to update
  62. the statistics each night using this SQL statement:
  63. </p><pre class="programlisting">
  64. REFRESH MATERIALIZED VIEW sales_summary;
  65. </pre><p>
  66. </p><p>
  67. Another use for a materialized view is to allow faster access to data
  68. brought across from a remote system through a foreign data wrapper.
  69. A simple example using <code class="literal">file_fdw</code> is below, with timings,
  70. but since this is using cache on the local system the performance
  71. difference compared to access to a remote system would usually be greater
  72. than shown here. Notice we are also exploiting the ability to put an
  73. index on the materialized view, whereas <code class="literal">file_fdw</code> does
  74. not support indexes; this advantage might not apply for other sorts of
  75. foreign data access.
  76. </p><p>
  77. Setup:
  78. </p><pre class="programlisting">
  79. CREATE EXTENSION file_fdw;
  80. CREATE SERVER local_file FOREIGN DATA WRAPPER file_fdw;
  81. CREATE FOREIGN TABLE words (word text NOT NULL)
  82. SERVER local_file
  83. OPTIONS (filename '/usr/share/dict/words');
  84. CREATE MATERIALIZED VIEW wrd AS SELECT * FROM words;
  85. CREATE UNIQUE INDEX wrd_word ON wrd (word);
  86. CREATE EXTENSION pg_trgm;
  87. CREATE INDEX wrd_trgm ON wrd USING gist (word gist_trgm_ops);
  88. VACUUM ANALYZE wrd;
  89. </pre><p>
  90. Now let's spell-check a word. Using <code class="literal">file_fdw</code> directly:
  91. </p><pre class="programlisting">
  92. SELECT count(*) FROM words WHERE word = 'caterpiler';
  93. count
  94. -------
  95. 0
  96. (1 row)
  97. </pre><p>
  98. With <code class="command">EXPLAIN ANALYZE</code>, we see:
  99. </p><pre class="programlisting">
  100. Aggregate (cost=21763.99..21764.00 rows=1 width=0) (actual time=188.180..188.181 rows=1 loops=1)
  101. -&gt; Foreign Scan on words (cost=0.00..21761.41 rows=1032 width=0) (actual time=188.177..188.177 rows=0 loops=1)
  102. Filter: (word = 'caterpiler'::text)
  103. Rows Removed by Filter: 479829
  104. Foreign File: /usr/share/dict/words
  105. Foreign File Size: 4953699
  106. Planning time: 0.118 ms
  107. Execution time: 188.273 ms
  108. </pre><p>
  109. If the materialized view is used instead, the query is much faster:
  110. </p><pre class="programlisting">
  111. Aggregate (cost=4.44..4.45 rows=1 width=0) (actual time=0.042..0.042 rows=1 loops=1)
  112. -&gt; Index Only Scan using wrd_word on wrd (cost=0.42..4.44 rows=1 width=0) (actual time=0.039..0.039 rows=0 loops=1)
  113. Index Cond: (word = 'caterpiler'::text)
  114. Heap Fetches: 0
  115. Planning time: 0.164 ms
  116. Execution time: 0.117 ms
  117. </pre><p>
  118. Either way, the word is spelled wrong, so let's look for what we might
  119. have wanted. Again using <code class="literal">file_fdw</code>:
  120. </p><pre class="programlisting">
  121. SELECT word FROM words ORDER BY word &lt;-&gt; 'caterpiler' LIMIT 10;
  122. word
  123. ---------------
  124. cater
  125. caterpillar
  126. Caterpillar
  127. caterpillars
  128. caterpillar's
  129. Caterpillar's
  130. caterer
  131. caterer's
  132. caters
  133. catered
  134. (10 rows)
  135. </pre><p>
  136. </p><pre class="programlisting">
  137. Limit (cost=11583.61..11583.64 rows=10 width=32) (actual time=1431.591..1431.594 rows=10 loops=1)
  138. -&gt; Sort (cost=11583.61..11804.76 rows=88459 width=32) (actual time=1431.589..1431.591 rows=10 loops=1)
  139. Sort Key: ((word &lt;-&gt; 'caterpiler'::text))
  140. Sort Method: top-N heapsort Memory: 25kB
  141. -&gt; Foreign Scan on words (cost=0.00..9672.05 rows=88459 width=32) (actual time=0.057..1286.455 rows=479829 loops=1)
  142. Foreign File: /usr/share/dict/words
  143. Foreign File Size: 4953699
  144. Planning time: 0.128 ms
  145. Execution time: 1431.679 ms
  146. </pre><p>
  147. Using the materialized view:
  148. </p><pre class="programlisting">
  149. Limit (cost=0.29..1.06 rows=10 width=10) (actual time=187.222..188.257 rows=10 loops=1)
  150. -&gt; Index Scan using wrd_trgm on wrd (cost=0.29..37020.87 rows=479829 width=10) (actual time=187.219..188.252 rows=10 loops=1)
  151. Order By: (word &lt;-&gt; 'caterpiler'::text)
  152. Planning time: 0.196 ms
  153. Execution time: 198.640 ms
  154. </pre><p>
  155. If you can tolerate periodic update of the remote data to the local
  156. database, the performance benefit can be substantial.
  157. </p></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="rules-views.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="rules-update.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">40.2. Views and the Rule System </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 40.4. Rules on <code class="command">INSERT</code>, <code class="command">UPDATE</code>, and <code class="command">DELETE</code></td></tr></table></div></body></html>
上海开阖软件有限公司 沪ICP备12045867号-1