diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml index 20426cda4ca..3ba037848f6 100644 --- a/doc/src/sgml/ref/repack.sgml +++ b/doc/src/sgml/ref/repack.sgml @@ -78,65 +78,70 @@ REPACK [ ( option [, ...] ) ] USING If the USING INDEX clause is specified, the rows in - the table are stored in the order that the index specifies; - clustering, because rows are physically clustered - afterwards. - If an index name is specified in the command, the order implied by that - index is used, and that index is configured as the index to cluster on. + the table are physically rearranged according to the ordering implied by + the specified index; this is known as clustering. + This can have performance implications: + in cases where you are accessing single rows randomly within a table, the + actual order of the data in the table is unimportant. However, if you tend + to access some data more than others, and there is an index that groups + them together, you will benefit from using clustering. If + you are requesting a range of indexed values from a table, or a single + indexed value that has multiple matching rows, + clustering will help because once the index identifies the + table page for the first row that matches, all other rows that match are + probably already on the same table page, and so you save disk accesses and + speed up the query. + + + + For B-Tree indexes, the ordering used by clustering is the index's linear + sort order. Other clusterable index access methods may use a different + ordering strategy, one which may not necessarily correspond to any SQL + sort order. + If an index name is specified in the command, that index is used and + is recorded as the table's clustering index. (This also applies to an index given to the CLUSTER command.) - If no index name is specified, then the index that has - been configured as the index to cluster on is used; an - error is thrown if none has. + If no index name is specified, then the index that has been configured as + the clustering one is used; if none has been configured, an error is thrown. An index can be set manually using ALTER TABLE ... CLUSTER ON, and reset with ALTER TABLE ... SET WITHOUT CLUSTER. + + Clustering is a one-time operation: when the table is + subsequently updated, the changes are not clustered. That is, no attempt + is made to store new or updated rows according to the clustering order. + (If one wishes, one can periodically recluster by issuing the command again. + Also, setting the table's fillfactor storage parameter + to less than 100% can aid in preserving cluster ordering during updates, + since updated rows are kept on the same page if enough space is available + there.) + + + + When clustering on a B-Tree index, REPACK can rewrite + the table using either an index scan on the specified index, or a + sequential scan followed by sorting. It will attempt to choose the method + that will be faster, based on planner cost parameters and available + statistical information. When clustering on an index of an access method + other than B-Tree, REPACK always uses an index scan. + + + + Because the planner records statistics about the ordering of tables, it is + advisable to specify the ANALYZE option, or to + run ANALYZE on the + newly repacked table. Otherwise, the planner might make poor choices of + query plans. + + If no table name is specified in REPACK USING INDEX, all tables which have a clustering index defined and which the calling user has privileges for are processed. - - Clustering is a one-time operation: when the table is - subsequently updated, the changes are not clustered. That is, no attempt - is made to store new or updated rows according to their index order. (If - one wishes, one can periodically recluster by issuing the command again. - Also, setting the table's fillfactor storage parameter - to less than 100% can aid in preserving cluster ordering during updates, - since updated rows are kept on the same page if enough space is available - there.) - - - - In cases where you are accessing single rows randomly within a table, the - actual order of the data in the table is unimportant. However, if you tend - to access some data more than others, and there is an index that groups - them together, you will benefit from using clustering. If - you are requesting a range of indexed values from a table, or a single - indexed value that has multiple rows that match, - clustering will help because once the index identifies the - table page for the first row that matches, all other rows that match are - probably already on the same table page, and so you save disk accesses and - speed up the query. - - - - REPACK can re-sort the table using either an index scan - on the specified index (if the index is a b-tree), or a sequential scan - followed by sorting. It will attempt to choose the method that will be - faster, based on planner cost parameters and available statistical - information. - - - - Because the planner records statistics about the ordering of tables, it is - advisable to - run ANALYZE on the - newly repacked table. Otherwise, the planner might make poor choices of - query plans. - diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c index 2924d884b10..1fa48f8fcc0 100644 --- a/src/backend/commands/repack.c +++ b/src/backend/commands/repack.c @@ -1429,10 +1429,12 @@ copy_table_data(Relation NewHeap, Relation OldHeap, Relation OldIndex, /* * Decide whether to use an indexscan or seqscan-and-optional-sort to scan - * the OldHeap. We know how to use a sort to duplicate the ordering of a - * btree index, and will use seqscan-and-sort for that case if the planner - * tells us it's cheaper. Otherwise, always indexscan if an index is - * provided, else plain seqscan. + * the OldHeap. If the index is a btree, ask the planner to choose via + * normal path cost comparison. + * + * The underlying tuplesort.c code doesn't support AMs other than btree, + * so we must always use a normal indexscan if a non-btree index is + * specified -- or an unsorted seqscan if no index is given. */ if (OldIndex != NULL && OldIndex->rd_rel->relam == BTREE_AM_OID) use_sort = plan_cluster_use_sort(RelationGetRelid(OldHeap),