AnalyticDB for MySQL allows you to query materialized views and provides the query rewrite feature. The query rewrite feature automatically rewrites queries to use materialized views and helps improve query performance. This topic describes how to use the query rewrite feature of materialized views.
Prerequisites
An AnalyticDB for MySQL cluster of V3.1.4.0 or later is created.
NoteTo query the minor version of an AnalyticDB for MySQL Data Lakehouse Edition cluster, execute the
SELECT adb_version();
statement. To update the minor version of a cluster, contact technical support.For information about how to view and update the minor version of an AnalyticDB for MySQL Data Warehouse Edition cluster, see Update the minor version of a cluster.
The following permissions are required to use materialized views:
To create a view, you must have the CREATE permission on databases or tables.
To refresh a materialized view, you must have the INSERT permission on databases or tables.
You must have the SELECT permission on the relevant table columns or all tables that are involved in a materialized view.
If you want to configure auto-refresh for a materialized view that you created, you must have permissions to refresh views by using the on-premises server (
127.0.0.1
) or an IP address ('%'
).
Overview
You can directly query materialized views or enable the query rewrite feature for materialized views. After you enable the query rewrite feature, queries that do not reference materialized views can be rewritten to use materialized views. In this case, materialized views are used as cache to accelerate queries without the need to modify SQL statements. AnalyticDB for MySQL allows you to rewrite a query that has the same structure as a materialized view and use rewrite rules to rewrite a query that is equivalent to a materialized view.
Query rewrite methods
AnalyticDB for MySQL checks whether the structure of a query statement is the same as the structure of a materialized view and selects an appropriate query rewrite method based on the check result. AnalyticDB for MySQL supports the following query rewrite methods:
Exact match rewrite
If the structure of a query statement is exactly the same as the structure of a materialized view, AnalyticDB for MySQL rewrites the query statement to use the materialized view. This is a simple and basic rewrite method that has few limits. For information about the limits, see the "Limits" section of this topic.
Advanced query rewrite
If the structure of a query statement is different from the structure of a materialized view, AnalyticDB for MySQL uses rewrite rules to check whether the materialized view contains the data required for the query. AnalyticDB for MySQL attempts to rewrite each part of the query and the subqueries. Different parts of the query may use different materialized views. For information about the supported rewrite range and limits of the advanced query rewrite method, see the "Rewrite range" and "Limits" sections of this topic.
Query rewrite levels
AnalyticDB for MySQL supports query rewrite only at the
STALE_TOLERATED
level. Queries can be rewritten to use materialized views to improve query performance even if the materialized views contain stale data that may not reflect the latest data of base tables. The STALE_TOLERATED level offers the maximum rewrite capability but may generate inaccurate query results. Before you use the query rewrite feature, we recommend that you refresh the materialized views to obtain the latest results. For more information, see Configure full refresh for materialized views.
Use the query rewrite feature
Enable the query rewrite feature
AnalyticDB for MySQL allows you to use one of the following methods to enable the query rewrite feature:
When you create a materialized view, specify the
ENABLE QUERY REWRITE
clause. For more information, see the "Parameters" section of the Create a materialized view topic.After you create a materialized view, execute the
ALTER MATERIALIZED VIEW <mv_name> ENABLE QUERY REWRITE;
statement. For more information, see Manage materialized views.
Disable the query rewrite feature
AnalyticDB for MySQL allows you to use one of the following methods to disable the query rewrite feature:
Execute the
ALTER MATERIALIZED VIEW <mv_name> DISABLE QUERY REWRITE;
statement. For more information, see Manage materialized views.Add a hint before an SQL statement to prevent the query from using the query rewrite feature. Syntax:
/*+MV_QUERY_REWRITE_ENABLED=false*/
SELECT ...
Example
Enable the query rewrite feature when you create a materialized view.
CREATE MATERIALIZED VIEW adb_mv REFRESH START WITH now() + interval 1 day ENABLE QUERY REWRITE AS SELECT course_id,course_name,max(course_grade) AS max_grade FROM tb_courses;
Execute a query.
SELECT course_id,course_name,max(course_grade) AS max_grade FROM tb_courses;
Execute the
EXPLAIN
statement to check whether the query rewrite feature takes effect.EXPLAIN SELECT course_id,course_name,max(course_grade) AS max_grade FROM tb_courses;
Sample result:
+---------------+ | Plan Summary | +---------------+ 1- Output[ Query plan ] {Est rowCount: 1.0} 2 -> Exchange[GATHER] {Est rowCount: 1.0} 3 - TableScan {table: adb_mv, Est rowCount: 1.0}
The preceding execution plan indicates that the query uses the data stored in the
adb_mv
materialized view, instead of the data in thetb_courses
table.
Limits
If a materialized view contains content that cannot be rewritten, the query rewrite feature does not take effect.
AnalyticDB for MySQL imposes different limits on the query rewrite feature for the exact match rewrite method and the advanced query rewrite method.
If a materialized view contains the following content, the exact match rewrite method does not take effect:
Nondeterministic functions, such as
NOW
,CURRENT_TIMESTAMP
, andRANDOM
User-defined functions (UDFs)
If a materialized view contains the following content, the advanced query rewrite method does not take effect:
ORDER BY, LIMIT, or OFFSET clause
UNION or UNION ALL clause
GROUPING SETS, CUBE, or ROLLUP in the GROUP BY clause
Window functions
FULL OUTER JOIN clause
System tables
Correlated subqueries
Nondeterministic functions, such as
NOW
,CURRENT_TIMESTAMP
, andRANDOM
UDFs
HAVING clause
SELF JOIN clause
If a query is contained in one of the following statements, the query rewrite feature does not take effect:
CREATE TABLE AS SELECT
INSERT INTO SELECT
INSERT OVERWRITE SELECT
REPLACE INTO SELECT
DELETE or UPDATE
Other scenarios
If a single-table query statement does not have filter conditions or aggregate functions, the query rewrite feature does not take effect.
Rewrite range
In the following examples, the same tables are used. Execute the following statements to create tables:
CREATE TABLE part (
partkey INTEGER NOT NULL,
name VARCHAR(55) NOT NULL,
type VARCHAR(25) NOT NULL
);
CREATE TABLE lineitem (
orderkey BIGINT,
partkey BIGINT NOT NULL,
suppkey BIGINT NOT NULL,
extendedprice DOUBLE NOT NULL,
discount DOUBLE NOT NULL,
returnflag CHAR(1) NOT NULL,
linestatus CHAR(1) NOT NULL,
shipdate DATE NOT NULL,
shipmode VARCHAR(25) NOT NULL,
commitdate DATE NOT NULL,
receiptdate DATE NOT NULL
);
CREATE TABLE orders (
orderkey BIGINT PRIMARY KEY,
custkey BIGINT NOT NULL,
orderstatus VARCHAR(1) NOT NULL,
totalprice DOUBLE NOT NULL,
orderdate DATE NOT NULL
);
CREATE TABLE partsupp (
partkey INTEGER NOT NULL PRIMARY KEY,
suppkey INTEGER NOT NULL,
availqty INTEGER NOT NULL,
supplycost DECIMAL(15,2) NOT NULL
);
Exact match rewrite
AnalyticDB for MySQL checks whether the structure of a query statement is the same as the structure of a materialized view. If the structures of the query statement and the materialized view are exactly the same, AnalyticDB for MySQL rewrites the query statement to use the materialized view.
Example
Execute a query statement.
SELECT l.returnflag, l.linestatus, SUM(l.extendedprice * (1 - l.discount)), COUNT(*) AS count_order FROM lineitem AS l GROUP BY l.returnflag, l.linestatus;
Create a materialized view.
CREATE MATERIALIZED VIEW mv0 REFRESH NEXT now() + interval 1 day ENABLE QUERY REWRITE AS SELECT l.returnflag, l.linestatus, SUM (l.extendedprice * (1 - l.discount)) AS sum_disc_price, count(*) AS count_order FROM lineitem AS l GROUP BY l.returnflag, l.linestatus;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT returnflag, linestatus, sum_disc_price, count_order FROM mv0;
Advanced query rewrite
If the structure of a query statement is different from the structure of a materialized view, AnalyticDB for MySQL uses rewrite rules to check the FILTER
, JOIN
, AGGREGATION
, and GROUP BY
expressions in sequence. Then, AnalyticDB for MySQL attempts to construct an equivalent query expression by using the materialized view to answer the query or a part of the query.
The advanced query rewrite method supports the following rewrite rules:
FILTER
If the predicate of a query statement is different from the predicate of a materialized view, AnalyticDB for MySQL uses the FILTER rule to construct a compensation expression. If the expression that is contained in the query statement does not exist in the materialized view, AnalyticDB for MySQL attempts to calculate the expression in the materialized view. Example:
Execute a query statement.
SELECT l.shipmode, l.extendedprice * (1 - l.discount) AS disc_price FROM orders AS o, lineitem AS l WHERE o.orderkey = l.orderkey AND l.shipmode in ('REG AIR', 'TRUCK') AND l.commitdate < l.receiptdate AND l.shipdate < l.commitdate;
Create a materialized view.
CREATE MATERIALIZED VIEW mv1 REFRESH NEXT now() + interval 1 day ENABLE QUERY REWRITE AS SELECT l.shipmode, l.extendedprice, l.discount FROM orders AS o, lineitem AS l WHERE o.orderkey = l.orderkey AND l.commitdate < l.receiptdate AND l.shipdate < l.commitdate;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT shipmode, extendedprice * (1 - discount) AS disc_price, discount FROM mv1 WHERE shipmode in ('REG AIR', 'TRUCK');
JOIN
AnalyticDB for MySQL supports inner joins, outer joins, left joins, and right joins for queries and materialized views. If the query and the materialized view contains different join relationships, AnalyticDB for MySQL attempts to calculate the join relationship required for the query based on the materialized view by using the JOIN rule. For example, AnalyticDB for MySQL filters a row of data in materialized views. This way, materialized views that contain outer joins can be used to calculate queries that contain inner join relationships. Example:
Execute a query statement.
SELECT p.type, p.partkey, ps.suppkey FROM part AS p, partsupp AS ps WHERE p.partkey = ps.partkey AND p.type NOT LIKE 'MEDIUM POLISHED%';
Create a materialized view.
CREATE MATERIALIZED VIEW mv2 REFRESH NEXT now() + INTERVAL 1 day ENABLE QUERY REWRITE AS SELECT p.type, p.partkey, ps.suppkey FROM partsupp AS ps INNER JOIN part AS p ON p.partkey = ps.partkey WHERE p.type NOT LIKE 'MEDIUM POLISHED%';
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT type, partkey, suppkey FROM mv2;
AGGREGATION
If the query or the materialized view uses different GROUP BY clauses or aggregate functions, AnalyticDB for MySQL constructs the same aggregate function from the materialized view by using the
AGGREGATION
rule. Example:Execute a query statement.
SELECT l.returnflag, l.linestatus, SUM(l.extendedprice * (1 - l.discount)) AS sum_disc_price FROM lineitem AS l GROUP BY l.returnflag, l.linestatus;
Create a materialized view.
CREATE MATERIALIZED VIEW mv3 REFRESH NEXT now() + INTERVAL 1 day ENABLE QUERY REWRITE AS SELECT l.returnflag, l.linestatus, SUM(l.extendedprice * (1 - l.discount)) AS sum_disc_price, COUNT(*) AS count_order FROM lineitem AS l GROUP BY l.returnflag, l.linestatus;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT returnflag, linestatus, sum_disc_price, count_order FROM mv3;
AGGREGATION ROLLUP
If the query and the materialized view use different GROUP BY fields, AnalyticDB for MySQL attempts to roll up the materialized view by using the
ROLLUP
rule. Example:Execute a query statement.
SELECT l.returnflag, SUM(l.extendedprice * (1 - l.discount)) AS sum_disc_price, COUNT(*) AS count_order FROM lineitem AS l WHERE l.returnflag = 'R' GROUP BY l.returnflag;
Create a materialized view.
CREATE MATERIALIZED VIEW mv4 REFRESH NEXT now() + INTERVAL 1 day ENABLE QUERY REWRITE AS SELECT l.returnflag, l.linestatus, SUM(l.extendedprice * (1 - l.discount)) AS sum_disc_price, COUNT(*) AS count_order FROM lineitem AS l GROUP BY l.returnflag, l.linestatus;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT returnflag, linestatus, sum_disc_price, count_order FROM mv4 WHERE returnflag = 'R' GROUP BY returnflag;
SUBQUERIES
If the query and the materialized view have different subqueries, AnalyticDB for MySQL attempts to rewrite the query by using the
SUBQUERIES
rule. Example:Execute a query statement.
SELECT p.type, p.partkey, ps.suppkey FROM part AS p, (SELECT * FROM partsupp WHERE suppkey > 10) ps WHERE p.partkey = ps.partkey;
Create a materialized view.
CREATE MATERIALIZED VIEW mv5 REFRESH NEXT now() + INTERVAL 1 day ENABLE QUERY REWRITE AS SELECT p.type, p.partkey, ps.suppkey FROM part AS p, partsupp AS ps WHERE p.partkey = ps.partkey;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT type, partkey, suppkey FROM mv5 WHERE suppkey > 10;
QUERY PARTIAL
If the table involved in the query does not exist in the materialized view, AnalyticDB for MySQL attempts to join the missing table to the materialized view by using the
QUERY PARTIAL
rule. Example:Execute a query statement.
SELECT p.type, p.partkey, ps.suppkey FROM part AS p, partsupp AS ps WHERE p.partkey = ps.partkey AND p.type NOT LIKE 'MEDIUM POLISHED%';
Create a materialized view.
CREATE MATERIALIZED VIEW mv6 REFRESH NEXT now() + INTERVAL 1 day ENABLE QUERY REWRITE AS SELECT p.type, p.partkey FROM part AS p WHERE p.type NOT LIKE 'MEDIUM POLISHED%';
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT mv6.type, mv6.partkey, ps.suppkey FROM mv6, partsupp AS ps WHERE mv6.partkey = ps.partkey;
UNION
If the materialized view contains only specific data required for the query, AnalyticDB for MySQL obtains specific query results from existing data of the materialized view and the remaining query results from base tables by using the
UNION
rule.Execute a query statement.
SELECT l.linestatus, COUNT(*) AS count_order FROM lineitem AS l WHERE l.shipdate >= DATE '1998-01-01' GROUP BY l.linestatus;
Create a materialized view.
CREATE MATERIALIZED VIEW mv7 REFRESH NEXT now() + interval 1 day ENABLE QUERY REWRITE AS SELECT l.linestatus, COUNT(*) AS count_order FROM lineitem AS l WHERE l.shipdate >= DATE '2000-01-01' GROUP BY l.linestatus;
If you execute the query statement after you enable the query rewrite feature for the materialized view, the query statement is rewritten as the following statement:
SELECT linestatus, count_order FROM ( SELECT linestatus, count_order FROM mv7 UNION ALL SELECT l.linestatus, COUNT(*) AS count_order FROM lineitem AS l WHERE l.shipdate >= DATE '1998-01-01' AND l.shipdate < DATE '1998-01-01' GROUP BY l.linestatus) GROUP BY linestatus;
FAQ
Q: Why does the query rewrite feature fail to take effect after I create a materialized view?
A: If the query rewrite feature does not take effect, perform the following operations:
Check whether you enabled the query rewrite feature for the materialized view. For more information, see the "Use the query rewrite feature" section of this topic.
Check whether the materialized view has limits. For more information, see the "Limits" section of this topic.
Check whether you have the SELECT permission on the materialized view. You can execute the
GRANT
statement to grant the required permissions to the database account that you want to use to perform queries. For more information, see the "Required permissions" section of the Query data from a materialized view topic.