Details on the MQT matching algorithm
What follows is a generalized discussion of how the MQT matching algorithm works.
The tables specified in the query and the MQT are examined. If the MQT and the query specify the same tables, then the MQT can potentially be used and matching continues. If the MQT references tables not referenced in the query, then the unreferenced table is examined to determine if it is a parent table in referential integrity constraint. If the foreign key is non-nullable and the two tables are joined using a primary key or foreign key equal predicate, then the MQT can still be potentially used.
Example 3
The MQT contains fewer tables than the query:
SELECT D.deptname, p.projname, sum(E.salary)
FROM DEPARTMENT D, EMPLOYEE E, EMPPROJACT EP, PROJECT P
WHERE D.deptno=E.workdept AND E.Empno=ep.empno
AND ep.projno=p.projno
GROUP BY D.DEPTNAME, p.projname
Create an MQT based on the preceding query:
CREATE TABLE MQT3
AS (SELECT D.deptname, sum(E.salary) as sum_sal, e.workdept, e.empno
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept
GROUP BY D.Deptname, e.workdept, e.empno)
DATA INITIALLY IMMEDIATE REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER
The rewritten query:
SELECT M.deptname, p.projname, SUM(M.sum_sal)
FROM MQT3 M, EMPPROJACT EP, PROJECT P
WHERE M.Empno=ep.empno AND ep.projno=p.projno
GROUP BY M.deptname, p.projname
All predicates specified in the MQT, must also be specified in the query. The query could contain additional predicates. Predicates specified in the MQT must match exactly the predicates in the query. Any additional predicates specified in the query, but not in the MQT must be able to be derived from columns projected from the MQT. See previous example 1.
Example 4
Set the total salary for all departments that are located in 'NY'.
SELECT D.deptname, sum(E.salary)
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept AND D.location = ?
GROUP BY D.Deptname
Create an MQT based on the preceding query:
CREATE TABLE MQT4
AS (SELECT D.deptname, D.location, sum(E.salary) as sum_sal
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept AND D.location = 'NY'
GROUP BY D.deptnamet, D.location)
DATA INITIALLY IMMEDIATE REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER
In this example, the constant 'NY' was replaced by a parameter marker and the MQT also had the local selection of location='NY' applied to it when the MQT was populated. The MQT matching algorithm matches the parameter marker and to the constant 'NY' in the predicate D.Location=?. It verifies that the values of the parameter marker are the same as the constant in the MQT; therefore the MQT can be used.
The MQT matching algorithm also attempts to match where the predicates between the MQT and the query are not the same. For example, if the MQT has a predicate SALARY > 50000, and the query has the predicate SALARY > 70000, the MQT contains the rows necessary to run the query. The MQT is used in the query, but the predicate SALARY > 70000 is left as selection in the query, so SALARY must be a column of the MQT.
Example 5
SELECT D.deptname, sum(E.salary)
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept AND D.location = 'NY'
GROUP BY D.deptname
Create an MQT based on the preceding query:
CREATE TABLE MQT5
AS (SELECT D.deptname, E.salary
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept)
DATA INITIALLY IMMEDIATE REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER
In this example, since D.Location is not a column of the MQT, the user query local selection predicate Location='NY' cannot be determined, so the MQT cannot be used.
Example 6
SELECT D.deptname, sum(E.salary)
FROM DEPARTMENT D, EMPLOYEE E
WHERE D.deptno=E.workdept
GROUP BY D.deptname
Create an MQT based on the preceding query:
CREATE TABLE MQT6(workdept, sumSalary)
AS (SELECT workdept, sum(salary)
FROM EMPLOYEE
GROUP BY workdept )
DATA INITIALLY IMMEDIATE REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER
In this example, the SUM(salary) aggregation is pushed down through the join to the EMPLOYEE table, allowing for a match and substitution of MQT6. A regrouping to (sum(sum(salary))) is defined at the top of the query to compensate for the grouping pushdown.
Instead of department joining to all the rows in the employee table, it now has the opportunity to join to the predetermined aggregates in MQT6. This type of MQT substitution can result in significant reduction of processing and IO.
If the MQT contains grouping, then the query must be a grouping query. The simplest case is where the MQT and the query specify the same list of grouping columns and column functions.
In some cases, if the MQT specifies group by columns that are a superset of query group by columns, the query can be rewritten to do regrouping. This regrouping reaggregates the groups of the MQT into the groups required by the query. When regrouping is required, the column functions need to be recomputed. The following table shows the supported regroup expressions.
The regrouping expression/aggregation rules are:
Query | MQT | Final query |
---|---|---|
COUNT(*) | COUNT(*) as cnt | SUM(cnt) |
COUNT(*) | COUNT(C2) as cnt2 (where c2 is non-nullable) | SUM(cnt2) |
COUNT(c1) | COUNT(c1) as cnt | SUM(cnt) |
COUNT(C1) (where C1 is non-nullable) | COUNT(C2) as cnt2 (where C2 is non-nullable) | SUM(cnt2) |
COUNT(distinct C1) | C1 as group_c1 (where C1 is a grouping column) | COUNT(group_C1) |
COUNT(distinct C1) | where C1 is not a grouping column | MQT not usable |
COUNT(C2) where C2 is from a table not in the MQT | COUNT(*) as cnt | cnt*COUNT(C2) |
COUNT(distinct C2) where C2 is from a table not in the MQT | Not applicable | COUNT(distinct C2) |
SUM(C1) | SUM(C1) as sm | SUM(sm) |
SUM(C1) | C1 as group_c1, COUNT(*) as cnt (where C1 is a grouping column) | SUM(group_c1 * cnt) |
SUM(C2) where C2 is from a table not in the MQT | COUNT(*) as cnt | cnt*SUM(C2) |
SUM(distinct C1) | C1 as group_c1 (where C1 is a grouping column) | SUM(group_C1) |
SUM(distinct C1) | where C1 is not a grouping column | MQT not usable |
SUM(distinct C2) where C2 is from a table not in the MQT | Not applicable | SUM(distinct C2) |
MAX(C1) | MAX(C1) as mx | MAX(mx) |
MAX(C1) | C1 as group_C1 (where C1 is a grouping column) | MAX(group_c1) |
MAX(C2) where C2 is from a table not in the MQT | Not applicable | MAX(C2) |
MIN(C1) | MIN(C1) as mn | MIN(mn) |
MIN(C1) | C1 as group_C1 (where C1 is a grouping column) | MIN(group_c1) |
MIN(C2) where C2 is from a table not in the MQT | Not applicable | MIN(C2) |
GROUPING(C1) | GROUPING(C1) as grp | grp |
GROUPING(C2) where C2 is from a table not in the MQT | Not applicable | GROUPING(C2) |
MQT matching does not support ARRAY_AGG, XMLAGG, and XMLGROUP grouping functions. AVG, STDDEV, STDDEV_SAMP, VARIANCE_SAMPand VAR_POP are calculated using combinations of COUNT and SUM. If AVG, STDDEV, or VAR_POP are included in the MQT and regroup requires recalculation of these functions, the MQT cannot be used. It is recommended that the MQT only use COUNT, SUM, MIN, and MAX. If the query contains AVG, STDDEV, or VAR_POP, it can be recalculated using COUNT and SUM.
If FETCH FIRST N ROWS is specified in the MQT, then FETCH FIRST N ROWS must also be specified in the query. Also, the number of rows specified for the MQT must be greater than or equal to the number of rows specified in the query. It is not recommended that an MQT contain the FETCH FIRST N ROWS clause.
The ORDER BY clause on the MQT can be used to order the data in the MQT if a REFRESH TABLE is run. It is ignored during MQT matching and if the query contains an ORDER BY clause, it is part of the rewritten query.