1- <sect1 id="pathman">
2- <title>pathman </title>
1+ <sect1 id="pg- pathman">
2+ <title>pg_pathman </title>
33 <para>
4- The <literal>pathman </literal> module provides optimized
4+ The <literal>pg_pathman </literal> module provides optimized
55 partitioning mechanism and functions to manage partitions.
66 </para>
7- <sect2 id="pathman-concepts">
8- <title>pathman Concepts</title>
7+ <sect2 id="pg- pathman-concepts">
8+ <title>pg_pathman Concepts</title>
99 <para>
1010 Partitioning refers to splitting one large table into smaller
1111 pieces. Each row in such table assigns to a single partition based
3636 For example:
3737 </para>
3838 <programlisting>
39- CHECK ( id >= 100 AND id < 200 )
40- CHECK ( id >= 200 AND id < 300 )
39+ CREATE TABLE test (id SERIAL PRIMARY KEY, title TEXT);
40+ CREATE TABLE test_1 (CHECK ( id >= 100 AND id < 200 )) INHERITS (test);
41+ CREATE TABLE test_2 (CHECK ( id >= 200 AND id < 300 )) INHERITS (test);
4142</programlisting>
4243 <para>
4344 Despite the flexibility of this approach it has weakness. If query
@@ -47,15 +48,15 @@ CHECK ( id >= 200 AND id < 300 )
4748 partitions is large the overhead may be significant.
4849 </para>
4950 <para>
50- The <literal>pathman </literal> module provides functions to manage
51- partitions and partitioning mechanism optimized based on knowledge
52- of the partitions structure. It stores partitioning configuration
53- in the <literal>pathman_config</literal> table, each row of which
54- contains single entry for partitioned table (relation name,
55- partitioning key and type). During initialization the
56- <literal>pathman </literal> module caches information about child
57- partitions in shared memory in form convenient to perform rapid
58- search. When user executes SELECT querypathman analyzes
51+ The <literal>pg_pathman </literal> module provides functions to
52+ manage partitions and partitioning mechanism optimized based on
53+ knowledge of the partitions structure. It stores partitioning
54+ configuration in the <literal>pathman_config</literal> table, each
55+ row of which contains single entry for partitioned table (relation
56+ name, partitioning key and type). During initialization the
57+ <literal>pg_pathman </literal> module caches information about
58+ child partitions in shared memory in form convenient to perform
59+ rapid search. When user executes SELECT querypg_pathman analyzes
5960 conditions tree looking for conditions like:
6061 </para>
6162 <programlisting>
@@ -72,32 +73,34 @@ WHERE id = 150
7273</programlisting>
7374 <para>
7475 Based on partitioning type and operator the
75- <literal>pathman </literal> searches corresponding partitions and
76- builds the plan.
76+ <literal>pg_pathman </literal> searches corresponding partitions
77+ and builds the plan.
7778 </para>
7879 </sect2>
79- <sect2 id="pathman-installation">
80+ <sect2 id="pg- pathman-installation">
8081 <title>Installation</title>
8182 <para>
8283 To install pathman run:
8384 </para>
8485 <programlisting>
85- CREATE EXTENSION pathman;
86+ CREATE SCHEMA pathman;
87+ CREATE EXTENSION pg_pathman SCHEMA pathman;
8688</programlisting>
8789 <para>
88- in your database Then modify shared_preload_libraries parameter
89- in postgresql.conf as following:
90+ Then modify <literal>shared_preload_libraries</>
91+ parameter in postgresql.conf as
92+ following:
9093 </para>
9194 <programlisting>
92- shared_preload_libraries = 'pathman '
95+ shared_preload_libraries = 'pg_pathman '
9396</programlisting>
9497 <para>
95- Then restart the &productname; instance.
98+ It will require to restart of the &productname; instance.
9699 </para>
97100 </sect2>
98- <sect2 id="pathman-functions">
101+ <sect2 id="pg- pathman-functions">
99102 <title>FUNCTIONS</title>
100- <sect3 id="partitions-creation">
103+ <sect3 id="pg-pathman- partitions-creation">
101104 <title>Partitions Creation</title>
102105 <programlisting>
103106create_hash_partitions(
@@ -143,16 +146,30 @@ create_range_partitions(
143146 <literal>TIMESTAMP</literal> partitioning keys.
144147 </para>
145148 </sect3>
146- <sect3 id="data-migration">
149+ <sect3 id="pg-pathman- data-migration">
147150 <title>Data migration</title>
148151 <programlisting>
149152partition_data(parent text)
150153</programlisting>
151154 <para>
152155 Copies data from parent table to its partitions.
153156 </para>
157+ <programlisting>
158+ create_hash_update_trigger(parent TEXT)
159+ </programlisting>
160+ <para>
161+ Creates the trigger on UPDATE for HASH partitions. The UPDATE
162+ trigger isn't created by default because of overhead. It is
163+ useful in cases when key attribute could be changed.
164+ </para>
165+ <programlisting>
166+ create_hash_update_trigger(parent TEXT)
167+ </programlisting>
168+ <para>
169+ Same as above for RANGE sections.
170+ </para>
154171 </sect3>
155- <sect3 id="partitions-management">
172+ <sect3 id="pg-pathman- partitions-management">
156173 <title>Partitions management</title>
157174 <programlisting>
158175split_range_partition(partition TEXT, value ANYELEMENT)
@@ -188,15 +205,15 @@ prepend_partition(p_relation TEXT)
188205disable_partitioning(relation TEXT)
189206</programlisting>
190207 <para>
191- Disables <literal>pathman </literal> partitioning mechanism for
192- the specified parent table and removes an insert trigger.
208+ Disables <literal>pg_pathman </literal> partitioning mechanism
209+ for the specified parent table and removes an insert trigger.
193210 Partitions itself remain unchanged.
194211 </para>
195212 </sect3>
196213 </sect2>
197- <sect2 id="examples">
214+ <sect2 id="pg-pathman- examples">
198215 <title>Examples</title>
199- <sect3 id="hash">
216+ <sect3 id="pg-pathman-example- hash">
200217 <title>HASH</title>
201218 <para>
202219 Consider an example of HASH partitioning. First create a table
@@ -222,9 +239,36 @@ SELECT create_hash_partitions('hash_rel', 'value', 100);
222239 </para>
223240 <programlisting>
224241SELECT partition_data('hash_rel');
242+ </programlisting>
243+ <para>
244+ Here is an example of the query with filtering by partitioning
245+ key and its plan:
246+ </para>
247+ <programlisting>
248+ SELECT * FROM hash_rel WHERE value = 1234;
249+ id | value
250+ ------+-------
251+ 1234 | 1234
252+
253+ EXPLAIN SELECT * FROM hash_rel WHERE value = 1234;
254+ QUERY PLAN
255+ -----------------------------------------------------------------
256+ Append (cost=0.00..2.00 rows=0 width=0)
257+ -> Seq Scan on hash_rel_34 (cost=0.00..2.00 rows=0 width=0)
258+ Filter: (value = 1234)
259+ </programlisting>
260+ <para>
261+ Note that pg_pathman exludes parent table from the query plan.
262+ To access parent table use ONLY modifier:
263+ </para>
264+ <programlisting>
265+ EXPLAIN SELECT * FROM ONLY hash_rel;
266+ QUERY PLAN
267+ --------------------------------------------------------
268+ Seq Scan on hash_rel (cost=0.00..0.00 rows=1 width=8)
225269</programlisting>
226270 </sect3>
227- <sect3 id="range">
271+ <sect3 id="pg-pathman-example- range">
228272 <title>RANGE</title>
229273 <para>
230274 Consider an example of RANGE partitioning. Create a table with
@@ -270,15 +314,93 @@ SELECT split_range_partition('range_rel_1', '2010-02-15'::date);
270314 </para>
271315 <programlisting>
272316SELECT append_partition('range_rel');
273- SELECT append_partition('range_rel');
317+ </programlisting>
318+ <para>
319+ Here is an example of the query with filtering by partitioning
320+ key and its plan:
321+ </para>
322+ <programlisting>
323+ SELECT * FROM range_rel WHERE dt >= '2012-04-30' AND dt <= '2012-05-01';
324+ id | dt
325+ -----+---------------------
326+ 851 | 2012-04-30 00:00:00
327+ 852 | 2012-05-01 00:00:00
328+
329+ EXPLAIN SELECT * FROM range_rel WHERE dt >= '2012-04-30' AND dt <= '2012-05-01';
330+ QUERY PLAN
331+ ----------------------------------------------------------------------------
332+ Append (cost=0.00..60.80 rows=0 width=0)
333+ -> Seq Scan on range_rel_28 (cost=0.00..30.40 rows=0 width=0)
334+ Filter: (dt >= '2012-04-30 00:00:00'::timestamp without time zone)
335+ -> Seq Scan on range_rel_29 (cost=0.00..30.40 rows=0 width=0)
336+ Filter: (dt <= '2012-05-01 00:00:00'::timestamp without time zone)
337+ </programlisting>
338+ </sect3>
339+ <sect3 id="disable-pg-pathman">
340+ <title>Disable pg_pathman</title>
341+ <para>
342+ To disable pg_pathman for some previously partitioned table use
343+ disable_partitioning() function:
344+ </para>
345+ <programlisting>
346+ SELECT disable_partitioning('range_rel');
347+ </programlisting>
348+ <para>
349+ All sections and data will stay available and will be handled by
350+ standard PostgreSQL partitioning mechanism. ### Manual
351+ partitions management It is possible to manage partitions
352+ manually. After creating or removing child tables it's necessary
353+ to invoke function:
354+ </para>
355+ <programlisting>
356+ on_update_partitions(oid),
357+ </programlisting>
358+ <para>
359+ which updates internal structures in memory of
360+ <literal>pg_pathman module</literal>. For example, let's create
361+ new section for the <literal>range_rel</literal> from above:
362+ </para>
363+ <programlisting>
364+ CREATE TABLE range_rel_archive (CHECK (dt >= '2000-01-01' AND dt < '2010-01-01')) INHERITS (range_rel);
365+ SELECT on_update_partitions('range_rel'::regclass::oid);
366+ </programlisting>
367+ <para>
368+ CHECK CONSTRAINT must have the exact format: * (VARIABLE >=
369+ CONST AND VARIABLE < CONST) for RANGE partitioned tables; *
370+ (VARIABLE % CONST = CONST) for HASH partitioned tables.
371+ </para>
372+ <para>
373+ It is possible to create partition from foreign table as well:
374+ </para>
375+ <programlisting>
376+ CREATE FOREIGN TABLE range_rel_archive (
377+ id INTEGER NOT NULL,
378+ dt TIMESTAMP)
379+ SERVER archive_server;
380+ ALTER TABLE range_rel_archive INHERIT range_rel;
381+ ALTER TABLE range_rel_archive ADD CHECK (dt >= '2000-01-01' AND dt < '2010-01-01');
382+ SELECT on_update_partitions('range_rel'::regclass::oid);
383+ </programlisting>
384+ <para>
385+ Foreign table structure must exactly match the parent table.
386+ </para>
387+ <para>
388+ In case when parent table is being dropped by DROP TABLE, you
389+ should invoke on_remove_partitions() function and delete
390+ particular entry from <literal>pathman_config</literal> table:
391+ </para>
392+ <programlisting>
393+ SELECT on_remove_partitions('range_rel'::regclass::oid);
394+ DROP TABLE range_rel CASCADE;
395+ DELETE FROM pathman_config WHERE relname = 'public.range_rel';
274396</programlisting>
275397 </sect3>
276398 </sect2>
277- <sect2 id="author">
399+ <sect2 id="pg-pathman- author">
278400 <title>Author</title>
279401 <para>
280402 Ildar Musin <email>i.musin@postgrespro.ru</email> Postgres
281- Professional Ltd., Russia
403+ Professional Ltd., Russia
282404 </para>
283405 </sect2>
284406</sect1>