diff --git a/README.md b/README.md index f8c4cdc..4d559d5 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ When `pg_ivm` is installed, the following objects are created. Use `create_immv` function to create IMMV. ``` -create_immv(immv_name text, view_definition text) RETURNS bigint +create_immv(immv_name text, view_definition text [, unlogged bool DEFAULT false]) RETURNS bigint ``` `create_immv` defines a new IMMV of a query. A table of the name `immv_name` is created and a query specified by `view_definition` is executed and used to populate the IMMV. The query is stored in `pg_ivm_immv`, so that it can be refreshed later upon incremental view maintenance. `create_immv` returns the number of rows in the created IMMV. @@ -94,6 +94,12 @@ When an IMMV is created, some triggers are automatically created so that the vie Note that if you use PostgreSQL 17 or later, while `create_immv` is running, the `search_path` is temporarily changed to `pg_catalog, pg_temp`. +In some cases (e.g. for very large IMMVs containing volatile data), and only if you really know what you are doing, it may be useful to create an IMMV without writing to the [PostgreSQL Write-Ahead Logs](https://www.postgresql.org/docs/current/wal-intro.html) (the underlying table is created with the `UNLOGGED` parameter). Unlogged tables improve write performance, reduce vacuum impact and produce fewer WALs (thus reducing network usage, backup size and restoration time). +```sql +SELECT create_immv('myview', 'SELECT * FROM mytab', true); +``` +**Important:** see the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-UNLOGGED) for unlogged tables **DRAWBACKS** (not replicated or included in physical backups, truncated in case of PostgreSQL crash, ...). + #### refresh_immv Use `refresh_immv` function to refresh IMMV. diff --git a/createas.c b/createas.c index 6218d16..12ad1c3 100644 --- a/createas.c +++ b/createas.c @@ -234,14 +234,22 @@ create_immv_nodata(List *tlist, IntoClause *into) */ ObjectAddress ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, - ParamListInfo params, QueryEnvironment *queryEnv, - QueryCompletion *qc) + bool unlogged, ParamListInfo params, + QueryEnvironment *queryEnv, QueryCompletion *qc) { Query *query = castNode(Query, stmt->query); IntoClause *into = stmt->into; bool do_refresh = false; ObjectAddress address; + /* + * For volatile data, it can be useful not to write to WALs. + * SEE THE POSTGRESQL DOCUMENTATION FOR DRAWBACKS (not replicated or included in physical backups, truncated in case of a crash, ...): + * https://www.postgresql.org/docs/current/sql-createtable.html#SQL-CREATETABLE-UNLOGGED + */ + if (unlogged) + into->rel->relpersistence = RELPERSISTENCE_UNLOGGED; + /* Check if the relation exists or not */ if (CreateTableAsRelExists(stmt)) return InvalidObjectAddress; diff --git a/pg_ivm.c b/pg_ivm.c index e2afc6f..bb0326c 100644 --- a/pg_ivm.c +++ b/pg_ivm.c @@ -173,6 +173,7 @@ create_immv(PG_FUNCTION_ARGS) { text *t_relname = PG_GETARG_TEXT_PP(0); text *t_sql = PG_GETARG_TEXT_PP(1); + bool unlogged = PG_GETARG_BOOL(2); char *relname = text_to_cstring(t_relname); char *sql = text_to_cstring(t_sql); List *parsetree_list; @@ -228,7 +229,7 @@ create_immv(PG_FUNCTION_ARGS) query = transformStmt(pstate, (Node *)ctas); Assert(query->commandType == CMD_UTILITY && IsA(query->utilityStmt, CreateTableAsStmt)); - ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, NULL, NULL, &qc); + ExecCreateImmv(pstate, (CreateTableAsStmt *) query->utilityStmt, unlogged, NULL, NULL, &qc); PG_RETURN_INT64(qc.nprocessed); } diff --git a/pg_ivm.h b/pg_ivm.h index 2c76f9b..069ff58 100644 --- a/pg_ivm.h +++ b/pg_ivm.h @@ -35,7 +35,7 @@ extern bool isImmv(Oid immv_oid); /* createas.c */ -extern ObjectAddress ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, +extern ObjectAddress ExecCreateImmv(ParseState *pstate, CreateTableAsStmt *stmt, bool unlogged, ParamListInfo params, QueryEnvironment *queryEnv, QueryCompletion *qc); extern void CreateIvmTriggersOnBaseTables(Query *qry, Oid matviewOid);