Clean duplicated code and some typos (#112)
Also, argument order mismatch of apply_new_delta_with_count() between declaration and definition is fixed.
This commit is contained in:
parent
b8de2801c7
commit
094add99f5
4 changed files with 18 additions and 19 deletions
|
|
@ -177,7 +177,7 @@ test=# SELECT * FROM immv WHERE aid = 1;
|
|||
(1 row)
|
||||
```
|
||||
|
||||
An appropriate index on IMMV is necessary for efficient IVM because we need to looks for tuples to be updated in IMMV. If there are no indexes, it will take a long time.
|
||||
An appropriate index on IMMV is necessary for efficient IVM because we need to look for tuples to be updated in IMMV. If there are no indexes, it will take a long time.
|
||||
|
||||
Therefore, when an IMMV is created by the `create_immv` function, a unique index is created on it automatically if possible. If the view definition query has a GROUP BY clause, a unique index is created on the columns of GROUP BY expressions. Also, if the view has DISTINCT clause, a unique index is created on all columns in the target list. Otherwise, if the IMMV contains all primary key attributes of its base tables in the target list, a unique index is created on these attributes. In other cases, no index is created.
|
||||
|
||||
|
|
@ -248,7 +248,7 @@ Recursive queries (`WITH RECURSIVE`) are not allowed. Unreferenced CTEs are not
|
|||
|
||||
`DISTINCT` is allowed in IMMV's definition queries. Suppose an IMMV defined with DISTINCT on a base table containing duplicate tuples. When tuples are deleted from the base table, a tuple in the view is deleted if and only if the multiplicity of the tuple becomes zero. Moreover, when tuples are inserted into the base table, a tuple is inserted into the view only if the same tuple doesn't already exist in it.
|
||||
|
||||
Physically, an IMMV defined with `DISTINCT` contains tuples after eliminating duplicates, and the multiplicity of each tuple is stored in a extra column named `__ivm_count__` that is added when such IMMV is created.
|
||||
Physically, an IMMV defined with `DISTINCT` contains tuples after eliminating duplicates, and the multiplicity of each tuple is stored in an extra column named `__ivm_count__` that is added when such IMMV is created.
|
||||
|
||||
### TRUNCATE
|
||||
|
||||
|
|
@ -257,7 +257,7 @@ When a base table is truncated, the IMMV is also truncated and the contents beco
|
|||
|
||||
### Concurrent Transactions
|
||||
|
||||
Suppose an IMMV is defined on two base tables and each table was modified in different a concurrent transaction simultaneously. In the transaction which was committed first, the IMMV can be updated considering only the change which happened in this transaction. On the other hand, in order to update the IMMV correctly in the transaction which was committed later, we need to know the changes occurred in both transactions. For this reason, `ExclusiveLock` is held on an IMMV immediately after a base table is modified in `READ COMMITTED` mode to make sure that the IMMV is updated in the latter transaction after the former transaction is committed. In `REPEATABLE READ` or `SERIALIZABLE` mode, an error is raised immediately if lock acquisition fails because any changes which occurred in other transactions are not be visible in these modes and IMMV cannot be updated correctly in such situations. However, as an exception if the IMMV has only one base table and doesn't use DISTINCT or GROUP BY, and the table is modified by `INSERT`, then the lock held on the IMMV is `RowExclusiveLock`.
|
||||
Suppose an IMMV is defined on two base tables and each table was modified in different a concurrent transaction simultaneously. In the transaction which was committed first, the IMMV can be updated considering only the change which happened in this transaction. On the other hand, in order to update the IMMV correctly in the transaction which was committed later, we need to know the changes occurred in both transactions. For this reason, `ExclusiveLock` is held on an IMMV immediately after a base table is modified in `READ COMMITTED` mode to make sure that the IMMV is updated in the latter transaction after the former transaction is committed. In `REPEATABLE READ` or `SERIALIZABLE` mode, an error is raised immediately if lock acquisition fails because any changes which occurred in other transactions are not visible in these modes and IMMV cannot be updated correctly in such situations. However, as an exception if the IMMV has only one base table and doesn't use DISTINCT or GROUP BY, and the table is modified by `INSERT`, then the lock held on the IMMV is `RowExclusiveLock`.
|
||||
|
||||
### Row Level Security
|
||||
|
||||
|
|
@ -267,7 +267,7 @@ If some base tables have row level security policy, rows that are not visible to
|
|||
|
||||
IVM is effective when we want to keep an IMMV up-to-date and small fraction of a base table is modified infrequently. Due to the overhead of immediate maintenance, IVM is not effective when a base table is modified frequently. Also, when a large part of a base table is modified or large data is inserted into a base table, IVM is not effective and the cost of maintenance can be larger than refresh from scratch.
|
||||
|
||||
In such situation, we can use `refesh_immv` function with `with_data = false` to disable immediate maintenance before modifying a base table. After a base table modification, call `refresh_immv`with `with_data = true` to refresh the view data and enable immediate maintenance.
|
||||
In such situation, we can use `refresh_immv` function with `with_data = false` to disable immediate maintenance before modifying a base table. After a base table modification, call `refresh_immv`with `with_data = true` to refresh the view data and enable immediate maintenance.
|
||||
|
||||
## Authors
|
||||
IVM Development Group
|
||||
|
|
|
|||
20
matview.c
20
matview.c
|
|
@ -2063,7 +2063,7 @@ apply_delta(Oid matviewOid, Tuplestorestate *old_tuplestores, Tuplestorestate *n
|
|||
/* apply new delta */
|
||||
if (use_count)
|
||||
apply_new_delta_with_count(matviewname, NEW_DELTA_ENRNAME,
|
||||
keys, aggs_set_new, &target_list_buf, count_colname,
|
||||
keys, &target_list_buf, aggs_set_new, count_colname,
|
||||
query->distinctClause != NULL);
|
||||
else
|
||||
apply_new_delta(matviewname, NEW_DELTA_ENRNAME, &target_list_buf);
|
||||
|
|
@ -2390,8 +2390,8 @@ get_null_condition_string(IvmOp op, const char *arg1, const char *arg2,
|
|||
/*
|
||||
* apply_old_delta_with_count
|
||||
*
|
||||
* Execute a query for applying a delta table given by deltname_old
|
||||
* which contains tuples to be deleted from to a materialized view given by
|
||||
* Execute a query for applying a delta table given by deltaname_old
|
||||
* which contains tuples to be deleted from a materialized view given by
|
||||
* matviewname. This is used when counting is required, that is, the view
|
||||
* has aggregate or distinct. Also, when a table in EXISTS sub queries
|
||||
* is modified.
|
||||
|
|
@ -2486,8 +2486,8 @@ apply_old_delta_with_count(const char *matviewname, const char *deltaname_old,
|
|||
/*
|
||||
* apply_old_delta
|
||||
*
|
||||
* Execute a query for applying a delta table given by deltname_old
|
||||
* which contains tuples to be deleted from to a materialized view given by
|
||||
* Execute a query for applying a delta table given by deltaname_old
|
||||
* which contains tuples to be deleted from a materialized view given by
|
||||
* matviewname. This is used when counting is not required.
|
||||
*/
|
||||
static void
|
||||
|
|
@ -2535,7 +2535,7 @@ apply_old_delta(const char *matviewname, const char *deltaname_old,
|
|||
/*
|
||||
* apply_new_delta_with_count
|
||||
*
|
||||
* Execute a query for applying a delta table given by deltname_new
|
||||
* Execute a query for applying a delta table given by deltaname_new
|
||||
* which contains tuples to be inserted into a materialized view given by
|
||||
* matviewname. This is used when counting is required, that is, the view
|
||||
* has aggregate or distinct. Also, when a table in EXISTS sub queries
|
||||
|
|
@ -2547,7 +2547,7 @@ apply_old_delta(const char *matviewname, const char *deltaname_old,
|
|||
*/
|
||||
static void
|
||||
apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
||||
List *keys, StringInfo aggs_set, StringInfo target_list,
|
||||
List *keys, StringInfo target_list, StringInfo aggs_set,
|
||||
const char* count_colname, bool distinct)
|
||||
{
|
||||
StringInfoData querybuf;
|
||||
|
|
@ -2603,7 +2603,7 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
"FROM %s AS diff "
|
||||
"WHERE %s " /* tuple matching condition */
|
||||
"RETURNING %s" /* returning keys of updated tuples */
|
||||
") INSERT INTO %s (%s)" /* insert a new tuple if this doesn't existw */
|
||||
") INSERT INTO %s (%s)" /* insert a new tuple if this doesn't exist */
|
||||
"SELECT %s FROM %s AS diff "
|
||||
"WHERE NOT EXISTS (SELECT 1 FROM updt AS mv WHERE %s);",
|
||||
matviewname, count_colname, count_colname, count_colname,
|
||||
|
|
@ -2621,7 +2621,7 @@ apply_new_delta_with_count(const char *matviewname, const char* deltaname_new,
|
|||
/*
|
||||
* apply_new_delta
|
||||
*
|
||||
* Execute a query for applying a delta table given by deltname_new
|
||||
* Execute a query for applying a delta table given by deltaname_new
|
||||
* which contains tuples to be inserted into a materialized view given by
|
||||
* matviewname. This is used when counting is not required.
|
||||
*/
|
||||
|
|
@ -3272,7 +3272,7 @@ getColumnNameStartWith(RangeTblEntry *rte, char *str, int *attnum)
|
|||
/*
|
||||
* isIvmName
|
||||
*
|
||||
* Check if this is a IVM hidden column from the name.
|
||||
* Check if this is an IVM hidden column from the name.
|
||||
*/
|
||||
bool
|
||||
isIvmName(const char *s)
|
||||
|
|
|
|||
8
pg_ivm.c
8
pg_ivm.c
|
|
@ -91,7 +91,7 @@ _PG_init(void)
|
|||
|
||||
/*
|
||||
* Given a C string, parse it into a qualified relation name
|
||||
* followed by a optional parenthesized list of column names.
|
||||
* followed by an optional parenthesized list of column names.
|
||||
*/
|
||||
static void
|
||||
parseNameAndColumns(const char *string, List **names, List **colNames)
|
||||
|
|
@ -201,7 +201,7 @@ create_immv(PG_FUNCTION_ARGS)
|
|||
|
||||
parsetree = linitial_node(RawStmt, parsetree_list);
|
||||
|
||||
/* view definition should spcify SELECT query */
|
||||
/* view definition should specify SELECT query */
|
||||
if (!IsA(parsetree->stmt, SelectStmt))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
|
|
@ -343,7 +343,7 @@ PgIvmImmvPrimaryKeyIndexId(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* Return the SELECT part of a IMMV
|
||||
* Return the SELECT part of an IMMV
|
||||
*/
|
||||
Datum
|
||||
get_immv_def(PG_FUNCTION_ARGS)
|
||||
|
|
@ -421,7 +421,7 @@ PgIvmObjectAccessHook(ObjectAccessType access, Oid classId,
|
|||
/*
|
||||
* isImmv
|
||||
*
|
||||
* Check if this is a IMMV from oid.
|
||||
* Check if this is an IMMV from oid.
|
||||
*/
|
||||
bool
|
||||
isImmv(Oid immv_oid)
|
||||
|
|
|
|||
1
pg_ivm.h
1
pg_ivm.h
|
|
@ -50,7 +50,6 @@ extern ObjectAddress ExecRefreshImmv(const RangeVar *relation, bool skipData,
|
|||
extern ObjectAddress RefreshImmvByOid(Oid matviewOid, bool skipData,
|
||||
const char *queryString, QueryCompletion *qc);
|
||||
extern bool ImmvIncrementalMaintenanceIsEnabled(void);
|
||||
extern Query *get_immv_query(Relation matviewRel);
|
||||
extern Datum IVM_immediate_before(PG_FUNCTION_ARGS);
|
||||
extern Datum IVM_immediate_maintenance(PG_FUNCTION_ARGS);
|
||||
extern Query* rewrite_query_for_exists_subquery(Query *query);
|
||||
|
|
|
|||
Loading…
Reference in a new issue