All Products
Search
Document Center

AnalyticDB:Query rewrite of materialized views

Last Updated:Aug 21, 2024

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 or later is created.

    Note

    For information about how to view the minor version of an AnalyticDB for MySQL cluster, see How do I view the minor version of a cluster? To update the minor version of a cluster, contact technical support.

  • 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 Refresh a materialized view.

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

  1. 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;
  2. Execute a query.

    SELECT course_id,course_name,max(course_grade) AS max_grade FROM tb_courses;
  3. 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 the tb_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, and RANDOM

      • 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, and RANDOM

      • 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:

      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%';
  • 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.