@@ -993,19 +993,25 @@ REFRESH MATERIALIZED VIEW sales_summary;
993993
994994<para>
995995 Another use for a materialized view is to allow faster access to data
996- brought across from a remote system, through a foreign data wrapper.
996+ brought across from a remote system through a foreign data wrapper.
997997 A simple example using <literal>file_fdw</literal> is below, with timings,
998998 but since this is using cache on the local system the performance
999- difference on a foreign data wrapper to a remote system could be greater.
999+ difference compared to access to a remote system would usually be greater
1000+ than shown here. Notice we are also exploiting the ability to put an
1001+ index on the materialized view, whereas <literal>file_fdw</literal> does
1002+ not support indexes; this advantage might not apply for other sorts of
1003+ foreign data access.
1004+ </para>
10001005
1006+ <para>
10011007 Setup:
10021008
10031009<programlisting>
10041010CREATE EXTENSION file_fdw;
10051011CREATE SERVER local_file FOREIGN DATA WRAPPER file_fdw;
10061012CREATE FOREIGN TABLE words (word text NOT NULL)
10071013 SERVER local_file
1008- OPTIONS (filename '/etc/dictionaries-common /words');
1014+ OPTIONS (filename '/usr/share/dict /words');
10091015CREATE MATERIALIZED VIEW wrd AS SELECT * FROM words;
10101016CREATE UNIQUE INDEX wrd_word ON wrd (word);
10111017CREATE EXTENSION pg_trgm;
@@ -1024,26 +1030,28 @@ SELECT count(*) FROM words WHERE word = 'caterpiler';
10241030(1 row)
10251031</programlisting>
10261032
1027- The plan is :
1033+ With <command>EXPLAIN ANALYZE</>, we see :
10281034
10291035<programlisting>
1030- Aggregate (cost=4125.19..4125.20 rows=1 width=0) (actual time=26.013..26.014 rows=1 loops=1)
1031- -> Foreign Scan on words (cost=0.00..4124.70 rows=196 width=0) (actual time=26.011..26.011 rows=0 loops=1)
1036+ Aggregate (cost=21763.99..21764.00 rows=1 width=0) (actual time=188.180..188.181 rows=1 loops=1)
1037+ -> Foreign Scan on words (cost=0.00..21761.41 rows=1032 width=0) (actual time=188.177..188.177 rows=0 loops=1)
10321038 Filter: (word = 'caterpiler'::text)
1033- Rows Removed by Filter: 99171
1034- Foreign File: /etc/dictionaries-common/words
1035- Foreign File Size: 938848
1036- Total runtime: 26.081 ms
1039+ Rows Removed by Filter: 479829
1040+ Foreign File: /usr/share/dict/words
1041+ Foreign File Size: 4953699
1042+ Planning time: 0.118 ms
1043+ Execution time: 188.273 ms
10371044</programlisting>
10381045
10391046 If the materialized view is used instead, the query is much faster:
10401047
10411048<programlisting>
1042- Aggregate (cost=4.44..4.45 rows=1 width=0) (actual time=0.074 ..0.074 rows=1 loops=1)
1043- -> Index Only Scan using wrd_word on wrd (cost=0.42..4.44 rows=1 width=0) (actual time=0.071 ..0.071 rows=0 loops=1)
1049+ Aggregate (cost=4.44..4.45 rows=1 width=0) (actual time=0.042 ..0.042 rows=1 loops=1)
1050+ -> 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)
10441051 Index Cond: (word = 'caterpiler'::text)
10451052 Heap Fetches: 0
1046- Total runtime: 0.119 ms
1053+ Planning time: 0.164 ms
1054+ Execution time: 0.117 ms
10471055</programlisting>
10481056
10491057 Either way, the word is spelled wrong, so let's look for what we might
@@ -1068,23 +1076,25 @@ SELECT word FROM words ORDER BY word <-> 'caterpiler' LIMIT 10;
10681076</programlisting>
10691077
10701078<programlisting>
1071- Limit (cost=2195.70..2195.72 rows=10 width=32) (actual time=218.904..218.906 rows=10 loops=1)
1072- -> Sort (cost=2195.70..2237.61 rows=16765 width=32) (actual time=218.902..218.904 rows=10 loops=1)
1073- Sort Key: ((word <-> 'caterpiler'::text))
1079+ Limit (cost=11583.61..11583.64 rows=10 width=32) (actual time=1431.591..1431.594 rows=10 loops=1)
1080+ -> Sort (cost=11583.61..11804.76 rows=88459 width=32) (actual time=1431.589..1431.591 rows=10 loops=1)
1081+ Sort Key: ((word <-> 'caterpiler'::text))
10741082 Sort Method: top-N heapsort Memory: 25kB
1075- -> Foreign Scan on words (cost=0.00..1833.41 rows=16765 width=32) (actual time=0.046..200.965 rows=99171 loops=1)
1076- Foreign File: /etc/dictionaries-common/words
1077- Foreign File Size: 938848
1078- Total runtime: 218.966 ms
1083+ -> Foreign Scan on words (cost=0.00..9672.05 rows=88459 width=32) (actual time=0.057..1286.455 rows=479829 loops=1)
1084+ Foreign File: /usr/share/dict/words
1085+ Foreign File Size: 4953699
1086+ Planning time: 0.128 ms
1087+ Execution time: 1431.679 ms
10791088</programlisting>
10801089
10811090 Using the materialized view:
10821091
10831092<programlisting>
1084- Limit (cost=0.28..1.02 rows=10 width=9) (actual time=24.916..25.079 rows=10 loops=1)
1085- -> Index Scan using wrd_trgm on wrd (cost=0.28..7383.70 rows=99171 width=9) (actual time=24.914..25.076 rows=10 loops=1)
1086- Order By: (word <-> 'caterpiler'::text)
1087- Total runtime: 25.884 ms
1093+ Limit (cost=0.29..1.06 rows=10 width=10) (actual time=187.222..188.257 rows=10 loops=1)
1094+ -> 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)
1095+ Order By: (word <-> 'caterpiler'::text)
1096+ Planning time: 0.196 ms
1097+ Execution time: 198.640 ms
10881098</programlisting>
10891099
10901100 If you can tolerate periodic update of the remote data to the local
0 commit comments