Coder Social home page Coder Social logo

cybertec-postgresql / pg_squeeze Goto Github PK

View Code? Open in Web Editor NEW
431.0 21.0 29.0 835 KB

A PostgreSQL extension for automatic bloat cleanup

License: Other

Makefile 0.18% C 83.46% PLpgSQL 10.52% Python 5.77% Emacs Lisp 0.06%
postgresql-extension postgresql

pg_squeeze's Introduction

PostgreSQL extension that removes unused space from a table and optionally sorts tuples according to particular index (as if CLUSTER command was executed concurrently with regular reads / writes). In fact we try to replace pg_repack extension.

While providing very similar functionality, pg_squeeze takes a different approach as it:

  1. Implements the functionality purely on server side.
  2. Utilizes recent improvements of PostgreSQL database server.

While (1) makes both configuration and use simpler (compared to pg_repack which uses both server and client side code), it also allows for rather smooth implementation of unattended processing using background workers.

As for (2), one important difference (besides the use of background workers) is that we use logical decoding instead of triggers to capture concurrent changes.

INSTALL

Install PostgreSQL before proceeding. Make sure to have pg_config binary, these are typically included in -dev and -devel packages.

git clone https://github.com/cybertec-postgresql/pg_squeeze.git
cd pg_squeeze
make
make install

Add these to postgresql.conf:

wal_level = logical
max_replication_slots = 1 # ... or add 1 to the current value.
shared_preload_libraries = 'pg_squeeze' # ... or add the library to the existing ones.

Restart the cluster, and invoke:

CREATE EXTENSION pg_squeeze;

Note: when upgrading a database cluster with pg_squeeze installed (either using pg_dumpall/restore or pg_upgrade), make sure that the new cluster has pg_squeeze in shared_preload_libraries before you upgrade, otherwise the upgrade will fail.

Register table for regular processing

First, make sure that your table has either primary key or unique constraint. This is necessary to process changes other transactions might do while pg_squeeze is doing its work.

To make the pg_squeeze extension aware of the table, you need to insert a record into squeeze.tables table. Once added, statistics of the table are checked periodically. Whenever the table meets criteria to be "squeezed", a "task" is added to a queue. The tasks are processed sequentially, in the order they were created.

The simplest "registration" looks like:

INSERT INTO squeeze.tables (tabschema, tabname, schedule)
VALUES ('public', 'foo', ('{30}', '{22}', NULL, NULL, '{3, 5}'));

Additional columns can be specified optionally, for example:

INSERT INTO squeeze.tables (
    tabschema,
    tabname,
    schedule,
    free_space_extra,
    vacuum_max_age,
    max_retry
)
VALUES (
    'public',
    'bar',
    ('{30}', '{22}', NULL, NULL, '{3, 5}'),
    30,
    '2 hours',
    2
);

Following is the complete description of table metadata.

  • tabschema and tabname are schema and table name respectively.

  • schedule column tells when the table should be checked, and possibly squeezed. The schedule is described by a value of the following composite data type, which resembles a crontab entry:

    CREATE TYPE schedule AS (
        minutes       minute[],
        hours         hour[],
        days_of_month dom[],
        months        month[],
        days_of_week  dow[]
    );
    

    Here, minutes (0-59) and hours (0-23) specify the time of the check within a day, while days_of_month (1-31), months (1-12) and days_of_week (0-7, where both 0 and 7 stand for Sunday) determine the day of the check.

    The check is performed if minute, hour and month all match the current timestamp, while NULL value means any minute, hour and month respectively. As for days_of_month and days_of_week, at least one of these needs to match the current timestamp, or both need to be NULL for the check to take place.

    For example, in the entries above tell that table public.bar should be checked every Wednesday and Friday at 22:30.

  • free_space_extra is the minimum percentage of extra free space needed to trigger processing of the table. The extra adjective refers to the fact that free space derived from fillfactor is not reason to squeeze the table.

    For example, if fillfactor is equal to 60, then at least 40 percent of each page should stay free during normal operation. If you want to ensure that 70 percent of free space makes pg_squeeze interested in the table, set free_space_extra to 30 (that is 70 percent required to be free minus the 40 percent free due to the fillfactor).

    Default value of free_space_extra is 50.

  • min_size is the minimum disk space in megabytes the table must occupy to be eligible for processing. The default value is 8.

  • vacuum_max_age is the maximum time since the completion of the last VACUUM to consider the free space map (FSM) fresh. Once this interval has elapsed, the portion of dead tuples might be significant and so more effort than simply checking the FSM needs to be spent to evaluate the potential effect pg_squeeze. The default value is 1 hour.

  • max_retry is the maximum number of extra attempts to squeeze a table if the first processing of the corresponding task failed. Typical reason to retry the processing is that table definition got changed while the table was being squeezed. If the number of retries is achieved, processing of the table is considered complete. The next task is created as soon as the next scheduled time is reached.

    The default value of max_retry is 0 (i.e. do not retry).

  • clustering_index is an existing index of the processed table. Once the processing is finished, tuples of the table will be physically sorted by the key of this index.

  • rel_tablespace is an existing tablespace the table should be moved into. NULL means that the table should stay where it is.

  • ind_tablespaces is a two-dimensional array in which each row specifies tablespace mapping of an index. The first and the second columns represent index name and tablespace name respectively. All indexes for which no mapping is specified will stay in the original tablespace.

    Regarding tablespaces, one special case is worth to mention: if tablespace is specified for table but not for indexes, the table gets moved to that tablespace but the indexes stay in the original one (i.e. the tablespace of the table is not the default for indexes as one might expect).

  • skip_analyze indicates that table processing should not be followed by ANALYZE command. The default value is false, meaning ANALYZE is performed by default.

squeeze.table is the only table user should modify. If you want to change anything else, make sure you perfectly understand what you are doing.

Ad-hoc processing for any table

It's also possible to squeeze tables manually without registering (i.e. inserting the corresponding record into squeeze.tables), and without prior checking of the actual bloat.

Function signature:

squeeze.squeeze_table(
    tabchema name,
    tabname name,
    clustering_index name,
    rel_tablespace name,
    ind_tablespaces name[]
)

Sample execution:

SELECT squeeze.squeeze_table('public', 'pgbench_accounts');

Note that the function is not transactional: it only starts a background worker, tells it which table it should process and exits. Rollback of the transaction the function was called in does not revert the changes done by the worker.

Enable / disable table processing

To enable processing of bloated tables, run this statement as superuser:

SELECT squeeze.start_worker();

The function starts a background worker (scheduler worker) that periodically checks which of the registered tables should be checked for bloat, and creates a task for each. Another worker (squeeze worker) is launched whenever a task exists for particular database.

If the scheduler worker is already running for the current database, the function does not report any error but the new worker will exit immediately.

If the workers are running for the current database, you can use the following statement to stop them:

SELECT squeeze.stop_worker();

Only the functions mentioned in this documentation are considered user interface. If you want to call any other one, make sure you perfectly understand what you're doing.

If you want the background workers to start automatically during startup of the whole PostgreSQL cluster, add entries like this to postgresql.conf file:

squeeze.worker_autostart = 'my_database your_database'
squeeze.worker_role = postgres

Next time you start the cluster, two or more workers (i.e. one scheduler worker and one or more squeeze workers) will be launched for my_database and the same for your_database. If you take this approach, note that any worker will either reject to start or will stop without doing any work if either:

  1. The pg_squeeze extension does not exist in the database, or

  2. squeeze.worker_role parameter specifies role which does not have the superuser privileges.

The functions/configuration variables explained above use singular form of the word worker although there are actually two workers. This is because only one worker existed in the previous versions of pg_squeeze, which ensured both scheduling and execution of the tasks. This implementation change is probably not worth to force all users to adjust their configuration files during upgrade.

Control the impact on other backends

Although the table being squeezed is available for both read and write operations by other transactions most of the time, exclusive lock is needed to finalize the processing. If pg_squeeze occasionally seems to block access to tables too much, consider setting squeeze.max_xlock_time GUC parameter. For example:

SET squeeze.max_xlock_time TO 100;

Tells that the exclusive lock shouldn't be held for more than 0.1 second (100 milliseconds). If more time is needed for the final stage, pg_squeeze releases the exclusive lock, processes changes committed by other transactions in between and tries the final stage again. Error is reported if the lock duration is exceeded a few more times. If that happens, you should either increase the setting or schedule processing of the problematic table to a different daytime, when the write activity is lower.

Running multiple workers per database

If you think that a single squeeze worker does not cope with the load, consider setting the squeeze.workers_per_database configuration variable to value higher than 1. Then the pg_squeeze extension will be able to process multiple tables at a time - one table per squeeze worker. However, be aware that this setting affects all databases in which you actively use the pg_squeeze extension. The total number of all the squeeze workers in the cluster (including the "scheduler workers") cannot exceed the in-core configuration variable max_worker_processes.

Monitoring

  • squeeze.log table contains one entry per successfully squeezed table.

    The columns tabschema and tabname identify the processed table. The columns started and finished tell when the processing started and finished. ins_initial is the number of tuples inserted into the new table storage during the "initial load stage", i.e. the number of tuples present in the table before the processing started. On the other hand, ins, upd and del are the numbers of tuples inserted, updated and deleted by applications during the table processing. (These "concurrent data changes" must also be incorporated into the squeezed table, otherwise they'd get lost.)

  • squeeze.errors table contains errors that happened during squeezing. An usual problem reported here is that someone changed definition (e.g. added or removed column) of the table whose processing was just in progress.

  • squeeze.get_active_workers() function returns a table of squeeze workers which are just processing tables in the current database.

    The pid column contains the system PID of the worker process. The other columns have the same meaning as their counterparts in the squeeze.log table. While the squeeze.log table only shows information on the completed squeeze operations, the squeeze.get_active_workers() function lets you check the progress during the processing.

Unregister table

If particular table should no longer be subject to periodical squeeze, simply delete the corresponding row from squeeze.tables table.

It's also a good practice to unregister table that you're going to drop, although the background worker does unregister non-existing tables periodically.

Upgrade

Make sure to install PostgreSQL and pg_config, see install section.

make # Compile the newer version.
pg_ctl -D /path/to/cluster stop # Stop the cluster.
make install
pg_ctl -D /path/to/cluster start # Start the cluster.

Connect to each database containing pg_squeeze and run this command:

ALTER EXTENSION pg_squeeze UPDATE;

Upgrade from 1.2.x

As there's no straightforward way to migrate the scheduling information (see the notes on the schedule column of the squeeze.tables table) automatically, and as the schedule column must not contain NULL values, the upgrade deletes the contents of the squeeze.tables table. Please export the table contents to a file before you perform the upgrade and configure the checks of those tables again as soon as the upgrade is done.

Concurrency

  1. The extension does not prevent other transactions from altering table at certain stages of the processing. If a "disruptive command" (i.e. ALTER TABLE, VACUUM FULL, CLUSTER or TRUNCATE) manages to commit before the squeeze could finish, the squeeze_table() function aborts and all changes done to the table are rolled back. The max_retry column of squeeze.tables table determines how many times the squeeze worker will retry. Besides that, change of schedule might help you to avoid disruptions.

  2. Like pg_repack, pg_squeeze also changes visibility of rows and thus allows for MVCC-unsafe behavior described in the first paragraph of mvcc-caveats.

Disk Space Requirements

Performing a full-table squeeze requires free disk space about twice as large as the target table and its indexes. For example, if the total size of the tables and indexes to be squeezed is 1GB, an additional 2GB of disk space is required.

pg_squeeze's People

Contributors

ahouska avatar df7cb avatar kmoppel avatar kovmir avatar laurenz avatar nikolays avatar simi avatar vmihailenco avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pg_squeeze's Issues

Use pg_squeeze for upgrading PKs from int4 to int8

There is a common problem: a table was created with int4 PK and, after some time, we have ~1B records in it, approaching int4's limit (2^31), so we need to change it to int8.

It would be great to use pg_squeeze for such a task. I'm not sure how difficult it would be to implement this although, right now this is just an idea โ€“ pg_repack also doesn't support it, while there is a significant demand in such feature.

Probleme install pg_squezze in step make

Hello,

I'm trying to install pg_squeeze in Ubuntu 16.04 and I'm using Postgresql 9.6 or 9.4
I am stuck at the make step, the errors are:

  • make: --pgxs: command not found
    make: *** No target. Stop.

  • gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision = standard -g -g - O2 -fstack-protector-strong -Wformat -Werror = format-security -fPIC -pie -fno-omit-frame-pointer -fPIC -I. -I./ -I / usr / include / postgresql / 9.6 / server -I / usr / include / postgresql / internal -Wdate-time -D_FORTIFY_SOURCE = 2 -D_GNU_SOURCE -I / usr / include / libxml2 -I / usr / include / mit-krb5 -c -o pg_squeeze.o pg_squeeze.c
    In file included from pg_squeeze.h: 12: 0,
    from pg_squeeze.c: 10:
    /usr/include/postgresql/internal/c.h:49:26: fatal error: postgres_ext.h: No such file or folder
    compilation terminated.
    : recipe for target "pg_squeeze.o" failed
    make: *** [pg_squeeze.o] Error 1

  • sometimes i have errror 127

i add in file Makefile : PGCONFIG=/usr/bin/pg_config or export PGCONFIG=/usr/bin/pg_config in CLI Ubuntu
I dont know what is problem and use command git clone https://github.com/cybertec-postgresql/pg_squeeze.git, wget https://github.com/cybertec-postgresql/pg_squeeze/archive/REL1_0_PG_9_6.tar.gz or git clone -b REL1_0_PG_9_6 https://github.com/cybertec-postgresql/pg_squeeze.git

Best regard
mrhasan60

PG11 support

IN GENERAL pg_squeeze (master branch) is working fine with PG11.

But from PG10 to PG11 the Background Worker struct changed and thus pg_stat_activity cannot work properly (e.g. the memory address for "background_type" of type char[] in pg11 is an int in pg10).

Please see the BackgroundWorker struct doc from PG11 vs. PG10.

Is it possible to make pg_squeeze PG11 compatible? There is no real alternative against index bloat (pg_repack comes with other problems)

Unexpected slowdown after unsuccessful space reclaim

Hi,

we have constant flow of new items into db. At one point we deleted significant partion of db and then scheduled pg_sqeeze (with xlock timeout 1s). When its worker starts squeezeing in one minute we got in squeeze.errors:

"squeeze_max_xlock_time" prevented squeeze from completion

and no space was reclaimed.

An issue is that flow of new items into db got slowed down quite a bit during next 2 hours. After slowdown db performance was recovered automatically. What would we expect is that db performance will be lowered for one minute but not for 2 hours. Do you have any explanation of this behavior or a way how to prevent that?

pg_squeeze 1.2
postgres 11.5

cancel pg_squeeze and delete temporary files

Hello,

I have some question for you.
Is it possible to cancel a squeeze or limit the creation of temporary files ?
If the squeeze was stop brutally and temporary files was not delete automaticly how do you delete files ?

kill other backends when timed out

Can you supplement the extension so that it kills blocking backends? When there are idle in transactions, using squeeze can result in a huge lock tree.

compile error

got compile errors with latest git:
git clone https://github.com/cybertec-postgresql/pg_squeeze.git ./pg_squeeze
cd pg_squeeze
export PATH=/usr/lib/postgresql/10/bin:$PATH

root@MICHAELV8:/pg_squeeze# make
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -fPIC -pie -fno-omit-frame-pointer -fPIC -I. -I./ -I/usr/include/postgresql/10/server -I/usr/include/postgresql/internal -I/usr/include/x86_64-linux-gnu -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include/mit-krb5 -c -o pg_squeeze.o pg_squeeze.c
pg_squeeze.c: In function โ€˜setup_decodingโ€™:
pg_squeeze.c:863:5: error: โ€˜LogicalDecodingContextโ€™ has no member named โ€˜fast_forwardโ€™
ctx->fast_forward = false;
^
pg_squeeze.c:880:2: error: too many arguments to function โ€˜MakeTupleTableSlotโ€™
dstate->tsslot = MakeTupleTableSlot(dstate->tupdesc_change);
^
In file included from /usr/include/postgresql/10/server/utils/tuplestore.h:34:0,
from /usr/include/postgresql/10/server/nodes/execnodes.h:28,
from pg_squeeze.h:23,
from pg_squeeze.c:10:
/usr/include/postgresql/10/server/executor/tuptable.h:142:24: note: declared here
extern TupleTableSlot *MakeTupleTableSlot(void);

Replica identiry 'full' not supported

Hi, is it a bug or feature? I can't find in the readme or on your website something about that.

postgres=# SELECT squeeze.squeeze_table('inventory', 'products', null, null, null);
ERROR:  Replica identity "full" not supported

I'm trying to use pg_squeeze instead of pg_repack because I suspect that pg_repack breaks replication slots/debezium, therefore replica identity full is necessary.

CREATE EXTENSION pg_squeeze ERROR

Hi, please can you help me?
When I type the command CREATE EXTENSION pg_squeeze I get an error:
ERROR: type "minute[]" does not exist.
Thanks

Support for Windows installation

How can it be installed on Windows?
I tried cmake / make but it fails.

C:\pg_squeeze-REL1_0_PG_10>cmake c:\pg_squeeze-REL1_0_PG_10
CMake Error: The source directory "C:/pg_squeeze-REL1_0_PG_10" does not appear to contain CMakeLists.txt.
Specify --help for usage, or press the help button on the CMake GUI.

Option to specify time intervals for the rebuilds

Would be excellent to have somekind of optional extra parameter for specifying maintenance windows for starting rebuild tasks. A list of time
intervals comes to my mind first if I think about - smth like
'{00:00,03:00}'::time[]. This would give zB couple of hours of night time even
to rebuild jobs that would be started at 3 AM.

ERROR: Failed to find target tuple

when working with PG10.5 we got ERROR: Failed to find target tuple
I did not get the reason for this error. Because there are other operations on the table parallel to squeeze? If this is the case, could you elaborate on the timing๏ผŸ THANK YOU!

PG12 support

Could you please add support for PG12?

Sadly the changes from PG11 to PG12 are too many for me to provide you with a proper patch: my C skills are not good enough.

I'd like to help testing the new PG12-squeeze when its done. Thanks!

PostgreSQL 14 support

Hi,

pg_squeeze 1.3.1 fails to compile against v14. v14 entered beta, and we started packaging stuff. Can you please take a look?

Thanks!

/usr/lib64/ccache/clang -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -O2 -I. -I./ -I/usr/pgsql-14/include/server -I/usr/pgsql-14/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include -flto=thin -emit-llvm -c -o pgstatapprox.bc pgstatapprox.c
concurrent.c: In function 'apply_concurrent_changes':
concurrent.c:301:57: warning: passing argument 1 of 'ExecInsertIndexTuples' from incompatible pointer type [-Wincompatible-pointer-types]
301 | recheck = ExecInsertIndexTuples(slot,
| ^~~~
| |
| TupleTableSlot *
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:612:51: note: expected 'ResultRelInfo *' but argument is of type 'TupleTableSlot *'
612 | extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~
concurrent.c:305:96: warning: passing argument 2 of 'ExecInsertIndexTuples' from incompatible pointer type [-Wincompatible-pointer-types]
305 | iistate->estate,
| ~~~~~~~^~~~~~~~
| |
| EState *
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:613:84: note: expected 'TupleTableSlot *' but argument is of type 'EState *'
613 | TupleTableSlot *slot, EState *estate,
| ~~~~~~~~~~~~~~~~^~~~
concurrent.c:301:35: error: too few arguments to function 'ExecInsertIndexTuples'
301 | recheck = ExecInsertIndexTuples(slot,
| ^~~~~~~~~~~~~~~~~~~~~
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:612:14: note: declared here
612 | extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
| ^~~~~~~~~~~~~~~~~~~~~
concurrent.c:400:73: warning: passing argument 1 of 'ExecInsertIndexTuples' from incompatible pointer type [-Wincompatible-pointer-types]
400 | recheck = ExecInsertIndexTuples(slot,
| ^~~~
| |
| TupleTableSlot *
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:612:51: note: expected 'ResultRelInfo *' but argument is of type 'TupleTableSlot *'
612 | extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~
concurrent.c:404:112: warning: passing argument 2 of 'ExecInsertIndexTuples' from incompatible pointer type [-Wincompatible-pointer-types]
404 | iistate->estate,
| ~~~~~~~^~~~~~~~
| |
| EState *
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:613:84: note: expected 'TupleTableSlot *' but argument is of type 'EState *'
613 | TupleTableSlot *slot, EState *estate,
| ~~~~~~~~~~~~~~~~^~~~
concurrent.c:400:51: error: too few arguments to function 'ExecInsertIndexTuples'
400 | recheck = ExecInsertIndexTuples(slot,
| ^~~~~~~~~~~~~~~~~~~~~
In file included from concurrent.c:17:
/usr/pgsql-14/include/server/executor/executor.h:612:14: note: declared here
612 | extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
| ^~~~~~~~~~~~~~~~~~~~~
concurrent.c: In function 'get_index_insert_state':
concurrent.c:513:47: error: 'EState' has no member named 'es_result_relation_info'; did you mean 'es_result_relations'?
513 | estate->es_result_relations = estate->es_result_relation_info =
| ^~~~~~~~~~~~~~~~~~~~~~~
| es_result_relations
concurrent.c:515:17: error: 'EState' has no member named 'es_num_result_relations'; did you mean 'es_result_relations'?
515 | estate->es_num_result_relations = 1;
| ^~~~~~~~~~~~~~~~~~~~~~~
| es_result_relations
make[1]: *** [: concurrent.o] Error 1
make[1]: *** Waiting for unfinished jobs....
pgstatapprox.c: In function 'statapprox_heap':
pgstatapprox.c:85:22: warning: implicit declaration of function 'GetOldestXmin' [-Wimplicit-function-declaration]
85 | OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM);
| ^~~~~~~~~~~~~
pgstatapprox.c:85:41: error: 'PROCARRAY_FLAGS_VACUUM' undeclared (first use in this function)
85 | OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM);
| ^~~~~~~~~~~~~~~~~~~~~~
pgstatapprox.c:85:41: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [: pgstatapprox.o] Error 1
pg_squeeze.c: In function 'setup_decoding':
pg_squeeze.c:909:9: error: too few arguments to function 'ReplicationSlotCreate'
909 | ReplicationSlotCreate(buf->data, true, RS_EPHEMERAL);
| ^~~~~~~~~~~~~~~~~~~~~
In file included from /usr/pgsql-14/include/server/replication/logical.h:15,
from pg_squeeze.h:28,
from pg_squeeze.c:10:
/usr/pgsql-14/include/server/replication/slot.h:206:13: note: declared here
206 | extern void ReplicationSlotCreate(const char *name, bool db_specific,
| ^~~~~~~~~~~~~~~~~~~~~
pg_squeeze.c: In function 'build_historic_snapshot':
pg_squeeze.c:1932:21: error: 'MyPgXact' undeclared (first use in this function)
1932 | xmin_save = MyPgXact->xmin;
| ^~~~~~~~
pg_squeeze.c:1932:21: note: each undeclared identifier is reported only once for each function it appears in
make[1]: *** [: pg_squeeze.o] Error 1
concurrent.c:308:15: error: too few arguments to function call, expected 7, have 5
NIL);
^
/usr/pgsql-14/include/server/executor/executor.h:612:14: note: 'ExecInsertIndexTuples' declared here
extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
^
concurrent.c:407:17: error: too few arguments to function call, expected 7, have 5
NIL);
^
/usr/pgsql-14/include/server/executor/executor.h:612:14: note: 'ExecInsertIndexTuples' declared here
extern List *ExecInsertIndexTuples(ResultRelInfo *resultRelInfo,
^
concurrent.c:513:40: error: no member named 'es_result_relation_info' in 'struct EState'; did you mean 'es_result_relations'?
estate->es_result_relations = estate->es_result_relation_info =
^~~~~~~~~~~~~~~~~~~~~~~
es_result_relations
/usr/pgsql-14/include/server/nodes/execnodes.h:574:18: note: 'es_result_relations' declared here
ResultRelInfo *es_result_relations; / Array of per-range-table-entry
^
concurrent.c:515:10: error: no member named 'es_num_result_relations' in 'struct EState'
estate->es_num_result_relations = 1;
~~~~~~ ^
4 errors generated.
make[1]: *** [/usr/pgsql-14/lib/pgxs/src/makefiles/../../src/Makefile.global:1051: concurrent.bc] Error 1
pgstatapprox.c:85:15: warning: implicit declaration of function 'GetOldestXmin' is invalid in C99 [-Wimplicit-function-declaration]
OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM);
^
pgstatapprox.c:85:34: error: use of undeclared identifier 'PROCARRAY_FLAGS_VACUUM'
OldestXmin = GetOldestXmin(rel, PROCARRAY_FLAGS_VACUUM);
^
1 warning and 1 error generated.
make[1]: *** [/usr/pgsql-14/lib/pgxs/src/makefiles/../../src/Makefile.global:1051: pgstatapprox.bc] Error 1
pg_squeeze.c:909:53: error: too few arguments to function call, expected 4, have 3
ReplicationSlotCreate(buf->data, true, RS_EPHEMERAL);
~~~~~~~~~~~~~~~~~~~~~ ^
/usr/pgsql-14/include/server/replication/slot.h:206:13: note: 'ReplicationSlotCreate' declared here
extern void ReplicationSlotCreate(const char *name, bool db_specific,
^
pg_squeeze.c:1932:14: error: use of undeclared identifier 'MyPgXact'
xmin_save = MyPgXact->xmin;
^
pg_squeeze.c:1933:2: error: use of undeclared identifier 'MyPgXact'
MyPgXact->xmin = InvalidTransactionId;
^
pg_squeeze.c:1945:2: error: use of undeclared identifier 'MyPgXact'
MyPgXact->xmin = xmin_save;
^
4 errors generated.
make[1]: *** [/usr/pgsql-14/li

Replication slot not being consumed during initial table copy

Test setup:

  1. Set up 100GB pgbench_accounts table.
  2. Update every row via UPDATE pgbench_accounts SET aid = aid;

That brings the table to 200GB, 250GB w/ thd primary key index on aid.

The server has a 750GB primary database volume with pg_wal on a separate, 70GB volume.

When testing (using v1.3) with both scheduled and ad-hoc runs I'm seeing that the replication slot is not having WAL data consumed while the initial table rebuild is happening. Would that not require more than at least 2x the space needed for the finished table build between the new table and the WAL file build-up and much more for an active server? Is that expected or is something perhaps off with my build/installation?

Documentation deviates from implementation

I just downloaded and installed 1.1 version of pg_squeeze, but when I run it based on the documentation, I get a bunch of errors for invalid column names, column types, etc.

For instance, documentation states this:

INSERT INTO squeeze.tables	(tabschema, tabname, first_check, task_interval, free_space_extra,
	vacuum_max_age, max_retry)
	VALUES	('public', 'bar', now(), '1 day', 30, '2 hours', 2);

But there is no first_check and task_interval in the squeeze.tables table, and now() is an invalid parameter type for schedule column. Here is the ddl of the squeeze.tables that I am running against:

     Column      |         Type          | Collation | Nullable |                  Default
------------------+-----------------------+-----------+----------+--------------------------------------------
 id               | integer               |           | not null | nextval('squeeze.tables_id_seq'::regclass)
 tabschema        | name                  |           | not null |
 tabname          | name                  |           | not null |
 clustering_index | name                  |           |          |
 rel_tablespace   | name                  |           |          |
 ind_tablespaces  | name[]                |           |          |
 schedule         | time with time zone[] |           | not null |
 free_space_extra | integer               |           | not null | 50
 min_size         | real                  |           | not null | 8
 vacuum_max_age   | interval              |           | not null | '01:00:00'::interval
 max_retry        | integer               |           | not null | 0
 skip_analyze     | boolean               |           | not null | false

Server Crash: segmentation fault

pg_squeeze caused a segmentation fault using pg_squeeze 1.1 on PG version 10.2.

Here is the log for starting a pg_squeeze worker, insert into squeeze.tables and segmentation fault that resulted:

2018-03-24 09:25:38 EDT [8787]: [5-1] user=postgres,db=testing,app=psql,client=[local] state=00000 LOG:  duration: 8.158 ms  statement: INSERT INTO squeeze.tables (tabschema, tabname, schedule, free_space_extra, vacuum_max_age, max_retry, clustering_index) VALUES ('public', 'sys_order', '{09:26, 23:00}', 10, '1 hours', 0, 'pk_order_id');
2018-03-24 09:25:47 EDT [8787]: [6-1] user=postgres,db=testing,app=psql,client=[local] state=00000 LOG:  duration: 0.669 ms  statement: SELECT squeeze.start_worker();
2018-03-24 09:26:33 EDT [8787]: [10-1] user=postgres,db=testing,app=psql,client=[local] state=00000 LOG:  duration: 1.950 ms  statement: select coalesce(datname,'N/A') as datname, pid, coalesce(usename, 'N/A') as usename, substring(application_name, 1,10) as app, wait_event, wait_event_type as we_type, state, backend_type, to_char(backend_start, 'YYYY-MM-DD HH24:MI:SS') as backend_start,  coalesce(to_char(state_change, 'YYYY-MM-DD HH24:MI:SS'), 'N/A') as state_change, coalesce(to_char(query_start, 'YYYY-MM-DD HH24:MI:SS'), 'N/A') as query_start, cast(EXTRACT(EPOCH FROM (now() - backend_start)) as integer) as conn_secs,(case when state <> 'active' then cast(EXTRACT(EPOCH FROM (now() - state_change)) as integer) else -1 end) as idle_secs,(case when state  = 'active' then cast(EXTRACT(EPOCH FROM (now() - query_start)) as integer) else -1 end) as q_secs, coalesce(substring(query,1,30), 'N/A') as query from pg_stat_activity;
2018-03-24 09:26:48 EDT [8831]: [1-1] user=,db=,app=,client= state=00000 LOG:  logical decoding found consistent point at 35/E73D4BF0
2018-03-24 09:26:48 EDT [8831]: [2-1] user=,db=,app=,client= state=00000 DETAIL:  There are no running transactions.
2018-03-24 09:26:48 EDT [8831]: [3-1] user=,db=,app=,client= state=00000 CONTEXT:  SQL statement "SELECT squeeze.squeeze_table(v_tabschema, v_tabname,
         v_cl_index, v_rel_tbsp, v_ind_tbsps, v_autovac, v_autovac_toast)"
        PL/pgSQL function squeeze.process_current_task() line 43 at PERFORM
        SQL statement "SELECT squeeze.process_current_task()"
2018-03-24 09:27:18 EDT [8710]: [7-1] user=,db=,app=,client= state=00000 LOG:  worker process: squeeze worker for database testing (PID 8831) was terminated by signal 11: Segmentation fault
2018-03-24 09:27:18 EDT [8710]: [8-1] user=,db=,app=,client= state=00000 DETAIL:  Failed process was running: SELECT squeeze.process_current_task()
2018-03-24 09:27:18 EDT [8710]: [9-1] user=,db=,app=,client= state=00000 LOG:  terminating any other active server processes
2018-03-24 09:27:18 EDT [8740]: [7-1] user=postgres,db=example,app=mysub,client=127.0.0.1 state=57P02 WARNING:  terminating connection because of crash of another server process
2018-03-24 09:27:18 EDT [8740]: [8-1] user=postgres,db=example,app=mysub,client=127.0.0.1 state=57P02 DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
2018-03-24 09:27:18 EDT [8740]: [9-1] user=postgres,db=example,app=mysub,client=127.0.0.1 state=57P02 HINT:  In a moment you should be able to reconnect to the database and repeat your command.

Support for different, yet compatible, DDL for the rewritten table

This is related to, a generalization, of #15. That issue provides a good example of a good use case.

Since pg_squeeze uses logical replication, it is possible to use a destination table with a DDL potentially different from that of the source table, as long as they are compatible. You may add NULLABLE, DEFAULT columns or even modify data types.

Doing an ALTER TABLE and then an UPDATE is a very heavy operation for many environments, rendering it unacceptable. The current fix is to write complex logic for progressive batch updates which is very failure prone.

I cannot estimate difficulty of this, as mentioned before, but I'd say it would be a very welcome addition.

Facing issues with writes when squeeze task is active for the table

We registered a table in squeeze.tables. The table was highly mutable. When the squeeze task was active on the table. Writes started to fail with following error.

Caused by: org.postgresql.util.PSQLException: ERROR: ON CONFLICT is not supported on table used as a catalog table

About streaming replication

Hello, I will build ha of pg by streaming replication mode.

If I change the parameter "wal_level" of settings from "logical" to "hot_standby" (and other relative parameters), will it work failed?

Do you have the doc for description about attentions?

worker_naptime parameter

Hello,
i can not change worker_naptime
i always face this :
ERROR: parameter "squeeze.worker_naptime" cannot be changed now

thanks

Tasks being run outside of scheduled times

I recently built pg_squeeze from master (0be3a4c) for Postgresql 11 and it's been working great for resolving our bloat issue. However, I have just noticed that it appears to be running tasks outside of the scheduled times.

This afternoon at 15:09 I deleted ~95 million rows from a table (anon_table_a) and at 15:10 the squeeze worker squeezed that table.

# SELECT * FROM squeeze.log;
 tabschema |   tabname    |            started            |           finished            
-----------+--------------+-------------------------------+-------------------------------
 public    | anon_table_a | 2020-06-24 09:46:40.831151+01 | 2020-06-24 09:54:08.416354+01
 public    | anon_table_c | 2020-06-26 22:58:23.275731+01 | 2020-06-26 22:58:28.436476+01
 public    | anon_table_a | 2020-07-01 15:10:18.912174+01 | 2020-07-01 15:14:20.960102+01

The issue is that it's scheduled to be squeezed between 22:00 and 07:00:

# SELECT * FROM squeeze.tables;
 id | tabschema |   tabname    | clustering_index | rel_tablespace | ind_tablespaces |         schedule          | free_space_extra | min_size | vacuum_max_age | max_retry | skip_analyze 
----+-----------+--------------+------------------+----------------+-----------------+---------------------------+------------------+----------+----------------+-----------+--------------
  1 | public    | anon_table_a |                  |                |                 | {22:00:00+01,07:00:00+01} |               20 |        8 | 01:00:00       |         0 | f
  2 | public    | anon_table_b |                  |                |                 | {22:00:00+01,07:00:00+01} |               20 |        8 | 01:00:00       |         0 | f
  3 | public    | anon_table_c |                  |                |                 | {22:00:00+01,07:00:00+01} |               20 |        8 | 01:00:00       |         0 | f

Now that I'm writing this I also notice that the first time that table was squeezed was also outside of the defined schedule.

Have I misconfigured, or perhaps misunderstood, something? Why are these tasks being run outside of the scheduled hours?

RAM requirements

I am getting following error in squeeze.errors when I am trying to squeeze 5GB table on server that has 3.5GB RAM (~500MB are reported to be free):

53200     | out of memory | Failed on request of size 2551

Log

2017-06-12 11:05:08 UTC [15483-1] LOG:  logical decoding found consistent point at 643/DC001558
2017-06-12 11:05:08 UTC [15483-2] DETAIL:  There are no running transactions.
2017-06-12 11:05:08 UTC [15483-3] CONTEXT:  SQL statement "SELECT squeeze.squeeze_table(v_tabschema, v_tabname,
         v_cl_index, v_rel_tbsp, v_ind_tbsps, v_autovac, v_autovac_toast)"
        PL/pgSQL function squeeze.process_current_task() line 43 at PERFORM
        SQL statement "SELECT squeeze.process_current_task()"
TopMemoryContext: 147024 total in 6 blocks; 73240 free (88 chunks); 73784 used
...
Grand total: 567637936 bytes in 348 blocks; 301691896 free (235427 chunks); 265946040 used

So I wonder how much RAM pg_squeeze requires...

Does not compile on Ubuntu 16.04 / Postgres 9.6.3

PG_CONFIG=/usr/bin/pg_config make
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -I/usr/include/mit-krb5 -fPIC -pie -fno-omit-frame-pointer -fpic -I. -I./ -I/usr/include/postgresql/9.6/server -I/usr/include/postgresql/internal -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2  -I/usr/include/tcl8.6  -c -o pg_squeeze.o pg_squeeze.c
pg_squeeze.c: In function โ€˜setup_decodingโ€™:
pg_squeeze.c:895:10: warning: passing argument 3 of โ€˜CreateInitDecodingContextโ€™ makes integer from pointer without a cast [-Wint-conversion]
          logical_read_local_xlog_page,
          ^
In file included from pg_squeeze.h:23:0,
                 from pg_squeeze.c:10:
/usr/include/postgresql/9.6/server/replication/logical.h:80:32: note: expected โ€˜bool {aka char}โ€™ but argument is of type โ€˜int (*)(XLogReaderState *, XLogRecPtr,  int,  XLogRecPtr,  char *, TimeLineID *) {aka int (*)(struct XLogReaderState *, long unsigned int,  int,  long unsigned int,  char *, unsigned int *)}โ€™
 extern LogicalDecodingContext *CreateInitDecodingContext(char *plugin,
                                ^
pg_squeeze.c:894:8: error: too few arguments to function โ€˜CreateInitDecodingContextโ€™
  ctx = CreateInitDecodingContext(REPL_PLUGIN_NAME, NIL,
        ^
In file included from pg_squeeze.h:23:0,
                 from pg_squeeze.c:10:
/usr/include/postgresql/9.6/server/replication/logical.h:80:32: note: declared here
 extern LogicalDecodingContext *CreateInitDecodingContext(char *plugin,
                                ^
<builtin>: recipe for target 'pg_squeeze.o' failed
make: *** [pg_squeeze.o] Error 1

Relevant link - http://www.postgresql-archive.org/pgsql-Don-t-use-on-disk-snapshots-for-exported-logical-decoding-snapsh-td5958816.html

[Feature] Enable squeezing of partitioned tables

Currently it errors with a "cannot squeeze partitioned table".

I think here the main consideration was that one could just run out of disk / WAL space as partitioned tables tend to be huge. But monitoring such situations should be users' responsibility and technically it should be allowed.

standbydefs.h no such file or directory while 'make'

I have add PG_CONFIG to my environment path, the value is /usr/bin/pg_config
then I run 'make', it fails with error
pg_squeeze.c:42:33: fatal error storage/standbydefs.h: No such file or directory.

my postgresql version is 9.5, is it why I am missing that .h file?
I have already installed postgresql-server-dev-9.5 on my system.

Does not compile on CentOS 7

export PG_CONFIG=/usr/pgsql-9.6/bin/pg_config
make
rd -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC -I. -I./ -I/usr/pgsql-9.6/inclu
de/server -I/usr/pgsql-9.6/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include -c -o pg_squeeze.o pg_squeeze.c
pg_squeeze.c: In function โ€˜check_prerequisitesโ€™:
pg_squeeze.c:735:23: error: โ€˜RELKIND_PARTITIONED_TABLEโ€™ undeclared (first use in this function)
if (form->relkind == RELKIND_PARTITIONED_TABLE)
^
pg_squeeze.c:735:23: note: each undeclared identifier is reported only once for each function it appears in
pg_squeeze.c: In function โ€˜setup_decodingโ€™:
pg_squeeze.c:851:10: error: too many arguments to function โ€˜CreateInitDecodingContextโ€™
NULL, NULL, NULL);
^
In file included from pg_squeeze.h:25:0,
from pg_squeeze.c:10:
/usr/pgsql-9.6/include/server/replication/logical.h:80:32: note: declared here
extern LogicalDecodingContext *CreateInitDecodingContext(char *plugin,
^
pg_squeeze.c:863:5: error: โ€˜LogicalDecodingContextโ€™ has no member named โ€˜fast_forwardโ€™
ctx->fast_forward = false;
^
pg_squeeze.c:880:2: error: too many arguments to function โ€˜MakeTupleTableSlotโ€™
dstate->tsslot = MakeTupleTableSlot(dstate->tupdesc_change);
^
In file included from /usr/pgsql-9.6/include/server/utils/tuplestore.h:34:0,
from /usr/pgsql-9.6/include/server/nodes/execnodes.h:25,
from pg_squeeze.h:23,
from pg_squeeze.c:10:
/usr/pgsql-9.6/include/server/executor/tuptable.h:142:24: note: declared here
extern TupleTableSlot *MakeTupleTableSlot(void);
^
pg_squeeze.c: In function โ€˜build_historic_snapshotโ€™:
pg_squeeze.c:1795:2: warning: implicit declaration of function โ€˜SnapBuildInitialSnapshotโ€™ [-Wimplicit-function-declaration]
result = SnapBuildInitialSnapshot(builder);
^
pg_squeeze.c:1795:9: warning: assignment makes pointer from integer without a cast [enabled by default]
result = SnapBuildInitialSnapshot(builder);
^
pg_squeeze.c: In function โ€˜perform_initial_loadโ€™:
pg_squeeze.c:1894:12: error: too many arguments to function โ€˜tuplesort_begin_clusterโ€™
false, false);
^
In file included from /usr/pgsql-9.6/include/server/nodes/execnodes.h:26:0,
from pg_squeeze.h:23,
from pg_squeeze.c:10:
/usr/pgsql-9.6/include/server/utils/tuplesort.h:66:24: note: declared here
extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
^
pg_squeeze.c:2100:5: error: too few arguments to function โ€˜tuplesort_getheaptupleโ€™
tup_out = tuplesort_getheaptuple(tuplesort, true);
^
In file included from /usr/pgsql-9.6/include/server/nodes/execnodes.h:26:0,
from pg_squeeze.h:23,
from pg_squeeze.c:10:
/usr/pgsql-9.6/include/server/utils/tuplesort.h:97:18: note: declared here
extern HeapTuple tuplesort_getheaptuple(Tuplesortstate *state, bool forward,
^
pg_squeeze.c: In function โ€˜create_transient_tableโ€™:
pg_squeeze.c:2246:3: error: too many arguments to function โ€˜heap_create_with_catalogโ€™
false, false, false, InvalidOid, NULL);
^
In file included from pg_squeeze.c:16:0:
/usr/pgsql-9.6/include/server/catalog/heap.h:54:12: note: declared here
extern Oid heap_create_with_catalog(const char *relname,
^
pg_squeeze.c: In function โ€˜build_transient_indexesโ€™:
pg_squeeze.c:2394:13: error: โ€˜INDEX_CREATE_IS_PRIMARYโ€™ undeclared (first use in this function)
flags |= INDEX_CREATE_IS_PRIMARY;
^
pg_squeeze.c:2508:12: warning: passing argument 7 of โ€˜index_createโ€™ makes integer from pointer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜Oidโ€™ but argument is of type โ€˜struct IndexInfo *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 8 of โ€˜index_createโ€™ makes integer from pointer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜Oidโ€™ but argument is of type โ€˜struct List *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 9 of โ€˜index_createโ€™ makes pointer from integer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜Oid *โ€™ but argument is of type โ€˜Oidโ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 10 of โ€˜index_createโ€™ makes pointer from integer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜Oid *โ€™ but argument is of type โ€˜Oidโ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 11 of โ€˜index_createโ€™ from incompatible pointer type [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜int16 *โ€™ but argument is of type โ€˜Oid *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 12 of โ€˜index_createโ€™ makes integer from pointer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜Datumโ€™ but argument is of type โ€˜Oid *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 13 of โ€˜index_createโ€™ makes integer from pointer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜boolโ€™ but argument is of type โ€˜int16 *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: warning: passing argument 19 of โ€˜index_createโ€™ makes integer from pointer without a cast [enabled by default]
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: expected โ€˜boolโ€™ but argument is of type โ€˜void *โ€™
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c:2508:12: error: too few arguments to function โ€˜index_createโ€™
NULL);
^
In file included from pg_squeeze.c:17:0:
/usr/pgsql-9.6/include/server/catalog/index.h:45:12: note: declared here
extern Oid index_create(Relation heapRelation,
^
pg_squeeze.c: In function โ€˜swap_relation_filesโ€™:
pg_squeeze.c:2808:2: warning: implicit declaration of function โ€˜CatalogTupleUpdateWithInfoโ€™ [-Wimplicit-function-declaration]
CatalogTupleUpdateWithInfo(relRelation, &reltup1->t_self, reltup1,
^
make: *** [pg_squeeze.o] Error 1

Question: insert only stmt

Hello,
imagine this use case, there is only insert in the table, no updates.
i cluster the table using the pk on 2 fields "store,id". As there is only insert stmt, new tuple will be added in new blocks.
To get new tuple in the same order as the pk,i should re-run 'cluster'.
How pg_squeeze could see that it have to squeeze, without being able to use 'free_space_extra' threshold ? because old block are 100 % full (no fillfactor on the table) ?
thanks

Problem to start the backgroud worker

Hi,

I work with pg_squeeze 1.3 on postgres 11.4 and linux 7.9
I Installed pg_squeeze with with the rpm pg_squeeze_11-1.3.1-1.rhel7.x86_64

Now I inserted a row into the table squeeze.tables

id | tabschema | tabname | clustering_index | rel_tablespace | ind_tablespaces | free_space_extra | min_size | vacuum_max_age | max_retry | skip_analyze | schedule
----+-----------+--------------------+------------------+----------------+-----------------+------------------+----------+----------------+-----------+--------------+--------------
1 | xxxxx | xxxxxxxxx | | | | 50 | 8 | 01:00:00 | 0 | f | ({0},{9},,,)

And I start the backgroud worker with

xxxxxxxx=# SELECT squeeze.start_worker();
start_worker

    18225

(1 row)

But in the Postgres log there is this error

2021-06-25 14:08:09.468 CEST [18225-1] @ (client=; app=) ERROR: function squeeze.add_new_tasks() does not exist at character 8
2021-06-25 14:08:09.468 CEST [18225-2] @ (client=; app=) HINT: No function matches the given name and argument types. You might need to add explicit type casts.
2021-06-25 14:08:09.468 CEST [18225-3] @ (client=; app=) QUERY: SELECT squeeze.add_new_tasks()
2021-06-25 14:08:09.470 CEST [42398-10] @ (client=; app=) LOG: background worker "squeeze worker for database xxxxxxxx" (PID 18225) exited with exit code 1

I'm doing something wrong ?

Many Thanks for your answer and Regards
Daniel

always occur operator for type 1043

when worker run, always occur
"Failed to find = operator for type 1043" ,
sql_state is XX000
table size is 16G, structure is:
uid character varying(128)
a integer[]
b integer[]
c integer[]

Make fails with Postgresql 11 on Ubuntu 18.04

When trying to build master (0be3a4c) with Postgresql 11 on Ubuntu 18.04 make fails because it can't find postgres_ext.h. Here are the commands that I'm using:

$ su -
# git clone https://github.com/cybertec-postgresql/pg_squeeze.git /usr/local/src/pg_squeeze
# which pg_config
/usr/bin/pg_config
# export PG_CONFIG="/usr/bin/pg_config"
# cd pg_squeeze/
# make
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -fPIC -I. -I./ -I/usr/include/postgresql/11/server -I/usr/include/postgresql/internal  -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2  -I/usr/include/mit-krb5  -c -o pg_squeeze.o pg_squeeze.c
In file included from pg_squeeze.h:12:0,
                 from pg_squeeze.c:10:
/usr/include/postgresql/internal/c.h:49:10: fatal error: postgres_ext.h: No such file or directory
 #include "postgres_ext.h"
          ^~~~~~~~~~~~~~~~
compilation terminated.
<builtin>: recipe for target 'pg_squeeze.o' failed
make: *** [pg_squeeze.o] Error 1

I can confirm that postgres_ext.h exists on the filesystem:

# locate postgres_ext.h
/usr/include/postgresql/postgres_ext.h

And that pg_config defines INCLUDEDIR correctly:

# pg_config
BINDIR = /usr/lib/postgresql/11/bin
DOCDIR = /usr/share/doc/postgresql-doc-11
HTMLDIR = /usr/share/doc/postgresql-doc-11
INCLUDEDIR = /usr/include/postgresql
PKGINCLUDEDIR = /usr/include/postgresql
INCLUDEDIR-SERVER = /usr/include/postgresql/11/server
LIBDIR = /usr/lib/x86_64-linux-gnu
PKGLIBDIR = /usr/lib/postgresql/11/lib
LOCALEDIR = /usr/share/locale
MANDIR = /usr/share/postgresql/11/man
SHAREDIR = /usr/share/postgresql/11
SYSCONFDIR = /etc/postgresql-common
PGXS = /usr/lib/postgresql/11/lib/pgxs/src/makefiles/pgxs.mk
CONFIGURE = '--build=x86_64-linux-gnu' '--prefix=/usr' '--includedir=/usr/include' '--mandir=/usr/share/man' '--infodir=/usr/share/info' '--sysconfdir=/etc' '--localstatedir=/var' '--disable-silent-rules' '--libdir=/usr/lib/x86_64-linux-gnu' '--libexecdir=/usr/lib/x86_64-linux-gnu' '--disable-maintainer-mode' '--disable-dependency-tracking' '--with-icu' '--with-tcl' '--with-perl' '--with-python' '--with-pam' '--with-openssl' '--with-libxml' '--with-libxslt' 'PYTHON=/usr/bin/python3' '--mandir=/usr/share/postgresql/11/man' '--docdir=/usr/share/doc/postgresql-doc-11' '--sysconfdir=/etc/postgresql-common' '--datarootdir=/usr/share/' '--datadir=/usr/share/postgresql/11' '--bindir=/usr/lib/postgresql/11/bin' '--libdir=/usr/lib/x86_64-linux-gnu/' '--libexecdir=/usr/lib/postgresql/' '--includedir=/usr/include/postgresql/' '--with-extra-version= (Ubuntu 11.8-1.pgdg18.04+1)' '--enable-nls' '--enable-integer-datetimes' '--enable-thread-safety' '--enable-tap-tests' '--enable-debug' '--enable-dtrace' '--disable-rpath' '--with-uuid=e2fs' '--with-gnu-ld' '--with-pgport=5432' '--with-system-tzdata=/usr/share/zoneinfo' '--with-llvm' 'LLVM_CONFIG=/usr/bin/llvm-config-6.0' 'CLANG=/usr/bin/clang-6.0' '--with-systemd' '--with-selinux' 'MKDIR_P=/bin/mkdir -p' 'TAR=/bin/tar' 'CFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer' 'LDFLAGS=-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now' '--with-gssapi' '--with-ldap' '--with-includes=/usr/include/mit-krb5' '--with-libs=/usr/lib/mit-krb5' '--with-libs=/usr/lib/x86_64-linux-gnu/mit-krb5' 'build_alias=x86_64-linux-gnu' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2' 'CXXFLAGS=-g -O2 -fstack-protector-strong -Wformat -Werror=format-security'
CC = gcc
CPPFLAGS = -Wdate-time -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include/mit-krb5
CFLAGS = -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer
CFLAGS_SL = -fPIC
LDFLAGS = -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/llvm-6.0/lib -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed
LDFLAGS_EX = 
LDFLAGS_SL = 
LIBS = -lpgcommon -lpgport -lpthread -lselinux -lxslt -lxml2 -lpam -lssl -lcrypto -lgssapi_krb5 -lz -ledit -lrt -lcrypt -ldl -lm 
VERSION = PostgreSQL 11.8 (Ubuntu 11.8-1.pgdg18.04+1)

Can you please help?

PostgreSQL 15 support

Hi,

1.4.1 does not build against v15. 15.0 is due in 2 weeks. Can you please take a look? Thanks! Devrim

/usr/lib64/ccache/clang -Wno-ignored-attributes -fno-strict-aliasing -fwrapv -Wno-unused-command-line-argument -Wno-compound-token-split-by-macro -O2 -I. -I./ -I/usr/pgsql-15/include/server -I/usr/pgsql-15/include/internal -D_GNU_SOURCE -I/usr/include/libxml2 -I/usr/include -flto=thin -emit-llvm -c -o pgstatapprox.bc pgstatapprox.c
pg_squeeze.c: In function 'squeeze_table_internal':
pg_squeeze.c:704:22: error: too few arguments to function 'GetFlushRecPtr'
704 | end_of_wal = GetFlushRecPtr();
| ^~~~~~~~~~~~~~
In file included from /usr/pgsql-15/include/server/utils/rel.h:18,
from /usr/pgsql-15/include/server/access/tableam.h:24,
from /usr/pgsql-15/include/server/access/heapam.h:22,
from pg_squeeze.h:18,
from pg_squeeze.c:10:
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: declared here
242 | extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
| ^~~~~~~~~~~~~~
pg_squeeze.c: In function 'perform_initial_load':
pg_squeeze.c:2081:17: error: too many arguments to function 'check_index_is_clusterable'
2081 | check_index_is_clusterable(rel_src, RelationGetRelid(cluster_idx),
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from pg_squeeze.c:33:
/usr/pgsql-15/include/server/commands/cluster.h:36:13: note: declared here
36 | extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~
pg_squeeze.c:2423:30: error: too few arguments to function 'GetFlushRecPtr'
2423 | end_of_wal = GetFlushRecPtr();
| ^~~~~~~~~~~~~~
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: declared here
242 | extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
| ^~~~~~~~~~~~~~
pg_squeeze.c: In function 'build_transient_indexes':
pg_squeeze.c:2927:30: error: too few arguments to function 'GetFlushRecPtr'
2927 | end_of_wal = GetFlushRecPtr();
| ^~~~~~~~~~~~~~
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: declared here
242 | extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
| ^~~~~~~~~~~~~~
pg_squeeze.c: In function 'perform_final_merge':
pg_squeeze.c:3096:9: warning: implicit declaration of function 'XLogBeginInsert'; did you mean 'XLogBeginRead'? [-Wimplicit-function-declaration]
3096 | XLogBeginInsert();
| ^~~~~~~~~~~~~~~
| XLogBeginRead
pg_squeeze.c:3097:9: warning: implicit declaration of function 'XLogRegisterData'; did you mean 'XLogRecGetData'? [-Wimplicit-function-declaration]
3097 | XLogRegisterData(&dummy_rec_data, 1);
| ^~~~~~~~~~~~~~~~
| XLogRecGetData
pg_squeeze.c:3098:27: warning: implicit declaration of function 'XLogInsert' [-Wimplicit-function-declaration]
3098 | xlog_insert_ptr = XLogInsert(RM_XLOG_ID, XLOG_NOOP);
| ^~~~~~~~~~
pg_squeeze.c:3100:22: error: too few arguments to function 'GetFlushRecPtr'
3100 | end_of_wal = GetFlushRecPtr();
| ^~~~~~~~~~~~~~
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: declared here
242 | extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
| ^~~~~~~~~~~~~~
pg_squeeze.c: In function 'get_heap_freespace':
pg_squeeze.c:3508:17: warning: implicit declaration of function 'RelationOpenSmgr'; did you mean 'RelationGetSmgr'? [-Wimplicit-function-declaration]
3508 | RelationOpenSmgr(rel);
| ^~~~~~~~~~~~~~~~
| RelationGetSmgr
make[1]: *** [: pg_squeeze.o] Error 1
make[1]: *** Waiting for unfinished jobs....
pg_squeeze.c:704:30: error: too few arguments to function call, single argument 'insertTLI' was not specified
end_of_wal = GetFlushRecPtr();
~~~~~~~~~~~~~~ ^
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: 'GetFlushRecPtr' declared here
extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
^
pg_squeeze.c:2082:19: error: too many arguments to function call, expected 3, have 4
false, NoLock);
^~~~~~
/usr/pgsql-15/include/server/storage/lockdefs.h:34:20: note: expanded from macro 'NoLock'
#define NoLock 0
^
/usr/pgsql-15/include/server/commands/cluster.h:36:13: note: 'check_index_is_clusterable' declared here
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
^
pg_squeeze.c:2423:31: error: too few arguments to function call, single argument 'insertTLI' was not specified
end_of_wal = GetFlushRecPtr();
~~~~~~~~~~~~~~ ^
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: 'GetFlushRecPtr' declared here
extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
^
pg_squeeze.c:2927:31: error: too few arguments to function call, single argument 'insertTLI' was not specified
end_of_wal = GetFlushRecPtr();
~~~~~~~~~~~~~~ ^
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: 'GetFlushRecPtr' declared here
extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
^
pg_squeeze.c:3096:2: warning: implicit declaration of function 'XLogBeginInsert' is invalid in C99 [-Wimplicit-function-declaration]
XLogBeginInsert();
^
pg_squeeze.c:3097:2: warning: implicit declaration of function 'XLogRegisterData' is invalid in C99 [-Wimplicit-function-declaration]
XLogRegisterData(&dummy_rec_data, 1);
^
pg_squeeze.c:3098:20: warning: implicit declaration of function 'XLogInsert' is invalid in C99 [-Wimplicit-function-declaration]
xlog_insert_ptr = XLogInsert(RM_XLOG_ID, XLOG_NOOP);
^
pg_squeeze.c:3100:30: error: too few arguments to function call, single argument 'insertTLI' was not specified
end_of_wal = GetFlushRecPtr();
~~~~~~~~~~~~~~ ^
/usr/pgsql-15/include/server/access/xlog.h:242:19: note: 'GetFlushRecPtr' declared here
extern XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI);
^
pg_squeeze.c:3508:3: warning: implicit declaration of function 'RelationOpenSmgr' is invalid in C99 [-Wimplicit-function-declaration]
RelationOpenSmgr(rel);
^

Question: How to estimate pg_squeeze run overhead properly?

Hello,

I have a table with 400 GB size. According to my estimations there is about 100 GB of bloat. I want to use pg_squeeze to release that space back to OS. Before run it I've performed some tests on small pgbench database to get some estimations about the overhead of potentional pg_squeeze run.

Test case
/*
 *************************************
 * PostgreSQL and pg_squeeze versions
 *************************************
 */

postgres@bench_db=# \dx pg_squeeze
                          List of installed extensions
    Name    | Version | Schema  |                  Description
------------+---------+---------+------------------------------------------------
 pg_squeeze | 1.3     | squeeze | A tool to remove unused space from a relation.
(1 row)

postgres@bench_db=# SELECT version();
                                                 version
---------------------------------------------------------------------------------------------------------
 PostgreSQL 12.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
(1 row)

/*
 ****************************************
 * Database/Table/Index size measurement
 ****************************************
 */

postgres@bench_db=# \l+ bench_db
                                                    List of databases
   Name   |   Owner   | Encoding |   Collate   |    Ctype    | Access privileges |  Size   |  Tablespace   | Description
----------+-----------+----------+-------------+-------------+-------------------+---------+---------------+-------------
 bench_db | bench_usr | UTF8     | en_US.UTF-8 | en_US.UTF-8 |                   | 7485 MB | bench_ts_data |
(1 row)

postgres@bench_db=# \i table_bloat_check.sql
 databasename | schemaname |    tablename     | can_estimate | est_rows | pct_bloat | mb_bloat | table_mb
--------------+------------+------------------+--------------+----------+-----------+----------+----------
 bench_db     | bench      | pgbench_accounts | t            | 50000000 |         1 |    94.04 | 6403.695
(1 row)

postgres@bench_db=# \i index_bloat_check.sql
 database_name | schema_name |    table_name    |      index_name       | bloat_pct | bloat_mb | index_mb | table_mb | index_scans
---------------+-------------+------------------+-----------------------+-----------+----------+----------+----------+-------------
 bench_db      | bench       | pgbench_accounts | pgbench_accounts_pkey |        11 |      115 | 1071.086 | 6403.695 |           0
(1 row)

/*
 ******************
 * Make some bloat
 ******************
 */

postgres@bench_db=# UPDATE bench.pgbench_accounts SET abalance = abalance + 100;
UPDATE 50000000

postgres@bench_db=# ANALYZE bench.pgbench_accounts ;
ANALYZE

/*
 ****************************************
 * Database/Table/Index size measurement
 ****************************************
 */

postgres@bench_db=# \l+ bench_db
                                                   List of databases
   Name   |   Owner   | Encoding |   Collate   |    Ctype    | Access privileges | Size  |  Tablespace   | Description
----------+-----------+----------+-------------+-------------+-------------------+-------+---------------+-------------
 bench_db | bench_usr | UTF8     | en_US.UTF-8 | en_US.UTF-8 |                   | 16 GB | bench_ts_data |
(1 row)

postgres@bench_db=# \i table_bloat_check.sql
 databasename | schemaname |    tablename     | can_estimate | est_rows | pct_bloat | mb_bloat | table_mb
--------------+------------+------------------+--------------+----------+-----------+----------+-----------
 bench_db     | bench      | pgbench_accounts | t            | 49853400 |        51 |  6516.23 | 12807.383
(1 row)

postgres@bench_db=# \i index_bloat_check.sql
 database_name | schema_name |    table_name    |      index_name       | bloat_pct | bloat_mb | index_mb | table_mb  | index_scans
---------------+-------------+------------------+-----------------------+-----------+----------+----------+-----------+-------------
 bench_db      | bench       | pgbench_accounts | pgbench_accounts_pkey |        70 |     2263 | 3216.969 | 12807.383 |           0
(1 row)

/*
 *
 * Total stats before squeeze
 *
 */

Total Space (table + index)		:		16023 MB
Total Bloat (table + index)		:		 8779 MB
Total Bloat % (table + index)           :		   55

/*
 *
 * Run pg_squeeze
 *
 */

postgres@bench_db=# \timing on
Timing is on.
postgres@bench_db=# SELECT squeeze.squeeze_table('bench', 'pgbench_accounts', null, null, null);

 squeeze_table
---------------

(1 row)

Time: 572472.659 ms (09:32.473)

/*
 ****************************************
 * Database/Table/Index size measurement
 ****************************************
 */
 
postgres@bench_db=# ANALYZE bench.pgbench_accounts ;
ANALYZE

postgres@bench_db=# \l+ bench_db
                                                    List of databases
   Name   |   Owner   | Encoding |   Collate   |    Ctype    | Access privileges |  Size   |  Tablespace   | Description
----------+-----------+----------+-------------+-------------+-------------------+---------+---------------+-------------
 bench_db | bench_usr | UTF8     | en_US.UTF-8 | en_US.UTF-8 |                   | 7485 MB | bench_ts_data |
(1 row)

postgres@bench_db=# \i table_bloat_check.sql
 databasename | schemaname |    tablename     | can_estimate | est_rows | pct_bloat | mb_bloat | table_mb
--------------+------------+------------------+--------------+----------+-----------+----------+----------
 bench_db     | bench      | pgbench_accounts | t            | 50000100 |         1 |    94.03 | 6403.695
(1 row)

postgres@bench_db=# \i index_bloat_check.sql
 database_name | schema_name |    table_name    |      index_name       | bloat_pct | bloat_mb | index_mb | table_mb | index_scans
---------------+-------------+------------------+-----------------------+-----------+----------+----------+----------+-------------
 bench_db      | bench       | pgbench_accounts | pgbench_accounts_pkey |        11 |      115 | 1071.086 | 6403.695 |           0
(1 row)
Grafana graphs during pg_squeeze run

image
image
image
image
image
image
image
image

Calculations:

I noticed the following: ~ 18 GB of additional space have been used during pg_squeeze run. ~ 7 GB is the new table size without bloat - okay, 1 GB of Temp files - okay, about 10 or so new WAL segments created, i.e. ~ 160 MB - okay. And about 10 GB occupied by pg_replslot directory.

Questions:

  1. If I want to to squeeze table with 400 GB (100 GB is bloat) in size - do I really have to have about 300 GB additional disk space + some space for Temp + some for WALs + a lot for pg_replslot.
  2. How to estimate pg_replslot size?
  3. Are there any formula on how to calculate pg_squeeze overhead. For me it looks like:
SpaceOverhead = NewTableSize + TempFiles + WalFiles + pgReplSlot

Are there any technics to reduce the impact of pg_replslot size?

Please advice.

Thanks.

Pg_squeeze with EDB Advanced Server?

Sorry for such a basic question and I am new to postgres. This is not so much an issue as just my lack of knowledge. Trying to get pg_squeeze extension working that we downloaded from community yum.repostitory build against EDB Advanced Server 11, but run into this error. Can anyone assist on what this means?

FATAL: incompatible library "/usr/edb/as11/lib/pg_squeeze.so": magic block mismatch
DETAIL: Server has FUNC_MAX_ARGS = 256, library has 100.

Squeeze temporary file

Hi! In the log of pg I see that process of squeeze creates temporary files when performing selec squeeze.squeeze_table... Which option can I increase so that temporary files are not created?

Ability for Redefinition of table.

As the Partitioning feature in PG12+ is great, there is a growing requirement among users to have a tool for converting a Non-partitioned table into a partitioned table. Currently, users do it with lot of downtime. Since pg_sqeeze has all the features to copy the data over to the new table definition, will it be possible to use it copying and swapping the table?
I hope if the user is allowed to specify a custom created transient_table, it should be achievable.
Sorry for my poor understanding of the code base and if I am completely wrong.

Scheduling pg_squeeze not working

Hello every body,

I had installing pg_squeeze 1.3.1 on PostgreSQL 10.5 whith RedHat 7.6.
I would like to schedule squeeze bloat table but this do not work.
1- I had create table "t_test"

mydb=# \d+ t_test
                                  Table "squeeze.t_test"
 Column |  Type   | Collation | Nullable | Default | Storage | Stats target | Description
--------+---------+-----------+----------+---------+---------+--------------+-------------
 id     | integer |           | not null |         | plain   |              |
Indexes:
    "t_test_pkey" PRIMARY KEY, btree (id)
mydb=# select count(*) from t_test;
  count
---------
 2000000
(1 row)

2- I had update all colomns ==> t_test table is bloated now.
3- parameter is setting:

mydb=# select name,setting  from pg_settings where name like '%squeeze.worker%';
           name           | setting
--------------------------+----------
 squeeze.worker_autostart | mydb
 squeeze.worker_role      | postgres
(2 rows)

4- squeeze is up

mydb=# \! ps fu -C postgres | grep squeeze
postgres 28109  0.0  0.3 1359496 10248 ?       Ss   Aug16   0:45  \_ postgres: bgworker: pg_squeeze squeeze worker for database mydb
postgres 28110  0.0  0.2 1359536 9232 ?        Ss   Aug16   0:45  \_ postgres: bgworker: pg_squeeze scheduler worker for database mydb

5- schedule time is added to squeeze.table

mydb=# select * from squeeze.tables\gx
id               | 1
tabschema        |  squeeze
tabname          | t_test
clustering_index |
rel_tablespace   |
ind_tablespaces  |
free_space_extra | 90
min_size         | 8
vacuum_max_age   | 00:10:00
max_retry        | 0
skip_analyze     | f
schedule         | ({31},{15},,,"{1,2,3,4,5,6,7}")

==> i had increasing/decreasing many times "free_space_extra, min_size and vacuum_max_age" values and looking after to test but nothing better!
6- nothing in "tasks, log and errors" tables not in pg_log either for pg_squeeze. (note "log_min_duration_statement = '0'")
7- however when i do "select squeeze.squeeze_table('squeeze','t_test', null, null, null);"
"t_test" is squeezed and table size goes from 138 MB to 69 MB.

*** My question is had i forgot some thing. Please help!
Thanks

Running squeeze causes continuous lag build up in logical replication architecture

Hello,

I have observed that running pg_squeeze on large tables either manually or on a schedule, leads to replication lag building constantly and requires intervention to prevent continuous WAL growth.

Our environment is Postgresql 12.1 running under Redhat 7.9, with pg_squeeze version 1.3:

test_db=# \! rpm -qa | grep squeeze
pg_squeeze_12-1.3.1-1.rhel7.x86_64

test_db=# \dx pg_squeeze
                          List of installed extensions
    Name    | Version | Schema  |                  Description
------------+---------+---------+------------------------------------------------
 pg_squeeze | 1.3     | squeeze | A tool to remove unused space from a relation.
(1 row)

One publisher replicates data to one subscriber. max_replication_slots and max_wal_senders are both set to 10 on the publisher, max_wal_senders is 20 on the subscriber and we currently have 6 subscriptions operating in total (one per schema to replicate).

Prior to running squeeze the replication slots on the publisher are all active and the subscription state is streaming:

test_db=# SELECT * FROM pg_replication_slots;
      slot_name      |  plugin  | slot_type | datoid |  database   | temporary | active | active_pid | xmin | catalog_xmin |  restart_lsn  | confirmed_flush_lsn
---------------------+----------+-----------+--------+-------------+-----------+--------+------------+------+--------------+---------------+---------------------
 sub1                | pgoutput | logical   |  16402 | test_db     | f         | t      |      21570 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
 sub2                | pgoutput | logical   |  16402 | test_db     | f         | t      |      23310 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
 sub3                | pgoutput | logical   |  16402 | test_db     | f         | t      |      23311 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
 sub4                | pgoutput | logical   |  16402 | test_db     | f         | t      |      23313 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
 sub5                | pgoutput | logical   |  16402 | test_db     | f         | t      |      23390 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
 sub6                | pgoutput | logical   |  16402 | test_db     | f         | t      |      23389 |      |    987626303 | 36E0/23DB3188 | 36E0/23F900F8
(6 rows)
test_db=# SELECT * FROM pg_stat_replication;
  pid  | usesysid |       usename       |  application_name   | client_addr  |         client_hostname         | client_port |         backend_start         | backend_xmin |   state   |   sent_lsn    |   write_lsn   |   flush_lsn   |  replay_lsn   |    write_lag    |    flush_lag    |   replay_lag    | sync_priority | sync_state |       
   reply_time
-------+----------+---------------------+---------------------+--------------+---------------------------------+-------------+-------------------------------+--------------+-----------+---------------+---------------+---------------+---------------+-----------------+-----------------+-----------------+---------------+------------+-------------------------------
 21570 |   991114 | logical_replication | sub1                | **.***.**.** | my.fqdn.org                     |       40072 | 2022-02-11 15:51:01.531025+08 |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.00045  | 00:00:00.00045  | 00:00:00.00045  |             0 | async      | 2022-02-21 15:32:17.793954+08
 23310 |   991114 | logical_replication | sub2                | **.***.**.** | my.fqdn.org                     |       40094 | 2022-02-11 15:51:06.703731+08 |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.000435 | 00:00:00.000435 | 00:00:00.000435 |             0 | async      | 2022-02-21 15:32:17.793945+08
 23311 |   991114 | logical_replication | sub3                | **.***.**.** | my.fqdn.org                     |       40096 | 2022-02-11 15:51:06.71485+08  |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.000411 | 00:00:00.000411 | 00:00:00.000411 |             0 | async      | 2022-02-21 15:32:17.793884+08
 23313 |   991114 | logical_replication | sub4                | **.***.**.** | my.fqdn.org                     |       40100 | 2022-02-11 15:51:06.726784+08 |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.000395 | 00:00:00.000395 | 00:00:00.000395 |             0 | async      | 2022-02-21 15:32:17.793891+08
 23390 |   991114 | logical_replication | sub5                | **.***.**.** | my.fqdn.org                     |       40204 | 2022-02-11 15:51:12.325621+08 |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.000588 | 00:00:00.000588 | 00:00:00.000588 |             0 | async      | 2022-02-21 15:32:17.793901+08
 23389 |   991114 | logical_replication | sub6                | **.***.**.** | my.fqdn.org                     |       40202 | 2022-02-11 15:51:12.322993+08 |              | streaming | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 36E0/285D19C0 | 00:00:00.000343 | 00:00:00.000343 | 00:00:00.000343 |             0 | async      | 2022-02-21 15:32:17.794075+08
(6 rows)

If I attempt to run the below on a large table within the sub1 publication that occupies 83GB on disk (68GB of this is bloat):

test_db=# \dt+ myschema.bloated_table;
                         List of relations
 Schema    |       Name        | Type  | Owner |  Size     | Description 
-----------+-------------------+-------+-------+--------+-------------
 myschema  | bloated_table     | table | myuser| 83 GB     |
(1 row)

test_db=# SELECT squeeze.squeeze_table('myschema', 'bloated_table', null, null, null);
 squeeze_table 
---------------

(1 row) 

The operation finishes successfully (reducing the size of the table dramatically), but replication has now lagged during the squeeze process and then never recovers:

test_db=# \dt+ myschema.bloated_table;
                       List of relations
 Schema    |       Name        | Type  | Owner |  Size     | Description 
-----------+-------------------+-------+-------+--------+-------------
 myschema  | bloated_table     | table | myuser| 9817 MB   |
(1 row)

test_db=# SELECT * FROM pg_replication_slots;
      slot_name      |  plugin  | slot_type | datoid |  database   | temporary | active | active_pid | xmin | catalog_xmin |  restart_lsn  | confirmed_flush_lsn
---------------------+----------+-----------+--------+-------------+-----------+--------+------------+------+--------------+---------------+---------------------
 sub1                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12535 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
 sub2                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12536 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
 sub3                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12537 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
 sub4                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12538 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
 sub5                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12539 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
 sub6                | pgoutput | logical   |  16402 | test_db     | f         | t      |      12540 |      |    988419346 | 36E3/2C8877A0 | 36E5/C43037F0
(6 rows)

test_db=# SELECT * FROM pg_stat_replication;
  pid  | usesysid |       usename       |  application_name   | client_addr  |         client_hostname          | client_port |         backend_start         | backend_xmin | state   |   sent_lsn    |   write_lsn   |   flush_lsn   |  replay_lsn   | write_lag | flush_lag | replay_lag | sync_priority | sync_state | reply_time
-------+----------+---------------------+---------------------+--------------+----------------------------------+-------------+-------------------------------+--------------+---------+---------------+---------------+---------------+---------------+-----------+-----------+------------+---------------+------------+-------------------------------
 12535 |   991114 | logical_replication | sub1                | **.***.**.** | my.fqdn.org                      |       56826 | 2022-02-22 10:56:55.3298+08   |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:28.787884+08
 12536 |   991114 | logical_replication | sub2                | **.***.**.** | my.fqdn.org                      |       56828 | 2022-02-22 10:56:55.339875+08 |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:28.776368+08
 12537 |   991114 | logical_replication | sub3                | **.***.**.** | my.fqdn.org                      |       56830 | 2022-02-22 10:56:55.350883+08 |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:28.73297+08
 12538 |   991114 | logical_replication | sub4                | **.***.**.** | my.fqdn.org                      |       56832 | 2022-02-22 10:56:55.361507+08 |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:29.009785+08
 12539 |   991114 | logical_replication | sub5                | **.***.**.** | my.fqdn.org                      |       56834 | 2022-02-22 10:56:55.371779+08 |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:28.800016+08
 12540 |   991114 | logical_replication | sub6                | **.***.**.** | my.fqdn.org                      |       56836 | 2022-02-22 10:56:55.382464+08 |              | catchup | 36E5/C430CA30 | 36E5/C43037F0 | 36E5/C43037F0 | 36E5/C43037F0 |           |           |            |             0 | async      | 2022-02-22 11:05:29.212577+08
(6 rows)

test_db=# \! du -sh /var/lib/pgsql/12/data/pg_wal
11G     /var/lib/pgsql/12/data/pg_wal

From the above we can see the slots are still active on the publisher but the subscription is now stuck in the catchup state (also the restart_lsn and confirmed_flush_lsn do not change) and the size of the pg_wal directory has now grown to 11GB and continues to grow over time.

Checking the subscriber logs shows the replication workers timing out as the squeeze process runs:

<2022-02-22 12:38:02 AEDT  >ERROR:  terminating logical replication worker due to timeout
<2022-02-22 12:38:02 AEDT  >LOG:  background worker "logical replication worker" (PID 5085) exited with exit code 1
<2022-02-22 12:38:02 AEDT  >LOG:  logical replication apply worker for subscription "sub3" has started
<2022-02-22 12:38:02 AEDT  >LOG:  background worker "logical replication worker" (PID 5148) exited with exit code 1
<2022-02-22 12:38:02 AEDT  >ERROR:  could not start WAL streaming: ERROR:  replication slot "sub3" is active for PID 23390

wal_sender_timeout is 5min on the publisher and 1min on the subscriber side.

At this point the only way to get the subscriptions working again is to DROP and CREATE them again, thus losing the built up WAL files. ALTER SUBSCRIPTION DISABLE/ENABLE has no effect and neither does restarting the postgresql-12 service on the subscriber side.

Is there a misconfiguration or setting I have overlooked here?

Please advise any suggestions as to how I can incorporate squeeze into our environment alongside our logical replication setup.

False Error Reported: dup index violation

I am using PG 10.2 on ubuntu 14.04 LTS using pg_squeeze 1.1.

I encountered the following error when attempting to squeeze the sys_order table with and without the clustering index:

testing=# INSERT INTO squeeze.tables (tabschema, tabname, schedule, free_space_extra, vacuum_max_age, max_retry, clustering_index) 
VALUES ('public', 'sys_order', '{10:00, 23:00}', 10, '1 hours', 0, 'pk_order_id');
ERROR:  duplicate key value violates unique constraint "tables_tabschema_tabname_key"
DETAIL:  Key (tabschema, tabname)=(public, sys_order) already exists.

testing=# INSERT INTO squeeze.tables (tabschema, tabname, schedule, free_space_extra, vacuum_max_age, max_retry) 
VALUES ('public', 'sys_order', '{10:00, 23:00}', 10, '1 hours', 0);
ERROR:  duplicate key value violates unique constraint "tables_tabschema_tabname_key"
DETAIL:  Key (tabschema, tabname)=(public, sys_order) already exists.
testing=# \dt+ squeeze.*

Here is the table DDL:
testing=# \d sys_order
Table "public.sys_order"
Column | Type | Collation | Nullable | Default
---------------+--------------------------+-----------+----------+---------------------------------------------
order_id | integer | | not null | nextval('sys_order_order_id_seq'::regclass)
product_id | integer | | not null |
item_count | integer | | not null |
order_dt | timestamp with time zone | | not null | now()
valid_dt | timestamp with time zone | | |
item_category | character(4) | | not null |
item_desc | character varying(50) | | not null |
extradata | numeric | | | (random() * (1000)::double precision)
Indexes:
"pk_order_id" PRIMARY KEY, btree (order_id)
"idx_order_order_dt" btree (order_dt)
"idx_product_id" btree (product_id, item_category)

Here is the SQL to validate I have no dups in the primary key and other indexes are not marked as unique.

select order_id, count(*) from sys_order group by order_id having count() > 1;
--> zero rows 

There is nothing generated in the squeeze.log or squeeze.error tables, or squeeze.tasks tables. It does generate 1 row in the squeeze.tables table:

testing=# select * from squeeze.tables;
-[ RECORD 1 ]----+--------------------------
id               | 1
tabschema        | public
tabname          | sys_order
clustering_index | pk_order_id
rel_tablespace   |
ind_tablespaces  |
schedule         | {10:00:00-04,23:00:00-04}
free_space_extra | 10
min_size         | 8
vacuum_max_age   | 01:00:00
max_retry        | 0
skip_analyze     | f

Also, since the key that is supposedly duped is called "tables_tabschema_tabname_key", I guess this is something internal to pg_squeeze about schemaname.tablename, but I only have one table in this database that is called sys_order, so it couldn't be related to duplicate tables with different schemas.

Disk space requirements of pg_squeeze?

I couldn't find any information about the disk space requirements of pg_squeeze.

My hope was that it doesn't require any additional space to squeeze a table, but experimentation showed, that it needs at least the size of the table.

The readme of pg_repack tells about the space requirement here. Maybe you can add a sentence to the readme of pg_squeeze as well?

Background is, that our servers from time to time run out of disk space. This is because we process a lot of short term data and if we forget to adjust data deletion processes after certain schema changes, the database blows up quickly. In this case the only way to delete old records and shrink the database space, is to add more disk space at first. This is cumbersome.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.