You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@calcite.apache.org by "Julian Hyde (Jira)" <ji...@apache.org> on 2021/07/28 22:33:00 UTC
[jira] [Created] (CALCITE-4707) Optimize incremental maintenance of
materialized views
Julian Hyde created CALCITE-4707:
------------------------------------
Summary: Optimize incremental maintenance of materialized views
Key: CALCITE-4707
URL: https://issues.apache.org/jira/browse/CALCITE-4707
Project: Calcite
Issue Type: Bug
Reporter: Julian Hyde
Optimize incremental maintenance of materialized views, when we know what DML has occurred since the last build.
The goal here is to develop an algebraic approach (i.e. new relational operators and transformation rules) that will generate an optimal query for maintaining the view.
Consider a materialized view
{code}
CREATE TABLE EmpsByDeptno AS
SELECT deptno, COUNT(*) AS c, SUM(sal) AS ss
FROM Emps
GROUP BY deptno;
{code}
We built it at time T1, when the value of {{Emps}} was {{Emps1}}, and it had the value {{EmpsByDeptno1}}.
It is now T2, and since then, new employees have been created in the {{NewEmps}} table. Thus {{Emps2 = Emps1 UNION ALL NewEmps}}. We could build a new MV,
{code}
CREATE TABLE EmpsByDeptno2 AS
SELECT deptno, COUNT(*) AS c, SUM(sal) AS ss
FROM (SELECT * FROM Emps1
UNION ALL
SELECT * FROM NewEmps)
GROUP BY deptno;
{code}but we would prefer to generate a DML command to modify {{EmpsByDeptno}} in place:{code}
MERGE INTO EmpsByDeptno AS e
USING (SELECT deptno, COUNT(*) AS c, SUM(sal) AS ss
FROM NewEmps) AS de
ON de.deptno = e.deptno
WHEN MATCHED THEN
UPDATE SET c = c + de.c, ss = ss + de.ss
WHEN NOT MATCHED THEN
INSERT (deptno, c, ss)
{code}
We propose two new relational operators:
* {{Diff(S, R)}} computes the difference between two relations. It has a same schema as R and S but with an additional column {{delta}}. Rows in S but not in R are called insertions, and have delta=1. Rows that are in R but not in S are called deletions, and have delta=-1.
* {{Patch(R, P)}} applies
The relational operators are named by analogy with the UNIX utilities {{diff}} and {{patch}}. (But {{Diff}}'s arguments are reversed compared to {{diff}}.) Consider:
{code}
grep r /usr/share/dict/words > r.txt
grep s /usr/share/dict/words > s.txt
diff r.txt s.txt > p.patch
patch -p1 r.txt < p.patch
cmp r.txt s.txt. # r and s are now identical
{code}
The relation {code}R = Patch(S, Diff(R, S)){code} always holds. {{Diff}} computes the difference between R and S, and when {{Patch}} applies that difference to {{S}} you get {{R}}.
{{Patch}} and {{Diff}} are intended by be generalizations of set operators. If there are only additions, i.e. {{R}} is a superset of {{S}}, then you can substitute {{Minus}} for {{Diff}}, and {{Union}} for {{Patch}}:
{code}
R = Union(S, Minus(R, S))
{code}
So, how do these relational operators solve our original problem?
An {{INSERT}} statement is assignment to a relation of itself union some new rows. ({{INSERT INTO R SELECT * FROM P}} is {{R ← R UNION P}}).
A {{MERGE}} statement is similar to {{INSERT}} but allows updates.
The {{MERGE}} query above is represented as {code}EmpsByDeptno ← Patch(EmpsByDeptno, Diff(NewEmpsByDeptno, EmpsByDeptno)){code}
Lastly we need relational transformation rules to optimize the expressions into per-key updates.
--
This message was sent by Atlassian Jira
(v8.3.4#803005)