---
title: "创建物化视图 - OceanBase 数据库 V4.3.2 | OceanBase 文档中心"
description: 创建物化视图 本文将向您介绍如何使用 SQL 语句创建物化视图。 说明 OceanBase 数据库暂时不支持直接修改物化视图的属性，如更新时间、刷新方法等。在这种情况下，可以考虑删除并重新创建物化视图以达到修改物化视图的目的。 权限要求 创建物化视图需要有 CREATE TABLE 权限。更多有关 OceanBase…
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*P8CuR4UJ_FkAAAAAAAAAAAAADiGDAQ/original) OceanBase 数据库分布式版 - V 4.3.2

# 创建物化视图

更新时间：2025-01-17 14:56:51

[编辑](https://github.com/oceanbase/oceanbase-doc/edit/V4.3.2/zh-CN/700.reference/300.database-object-management/200.manage-object-of-oracle-mode/500.manage-views-of-oracle-mode/200.manage-materialized-views-of-oracle-mode/100.materialized-views-of-oracle-mode/200.create-materialized-views-of-oracle-mode.md)  

本文将向您介绍如何使用 SQL 语句创建物化视图。

#### 说明

OceanBase 数据库暂时不支持直接修改物化视图的属性，如更新时间、刷新方法等。在这种情况下，可以考虑删除并重新创建物化视图以达到修改物化视图的目的。

## 权限要求

创建物化视图需要有 `CREATE TABLE` 权限。更多有关 OceanBase 数据库权限的详细介绍，请参见 [Oracle 模式下的权限分类](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001052867)。

## 语法

创建物化视图的 SQL 语句格式如下：

```sql
CREATE MATERIALIZED VIEW view_name [([column_list] [PRIMARY KEY(column_list)])] [table_option_list] [partition_option] [refresh_clause [query_rewrite_clause] [on_query_computation_clause]] AS view_select_stmt;

```

有关创建物化视图语法的详细参数说明信息，请参见 [CREATE MATERIALIZED VIEW](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001054359)。

### 创建测试表

1. 创建表 `tbl1`。

   ```sql
   CREATE TABLE tbl1 (id NUMBER PRIMARY KEY, name VARCHAR2(20), age NUMBER);

   ```
 2. 创建表 `tbl2`。

   ```sql
   CREATE TABLE tbl2 (id NUMBER PRIMARY KEY, tbl1_id NUMBER NOT NULL, notes VARCHAR2(50),
     CONSTRAINT fk_tbl2  FOREIGN KEY (tbl1_id)  REFERENCES tbl1 (id));

   ```
 3. 创建表 `tbl3`。

   ```sql
   CREATE TABLE tbl3 (col1 NUMBER PRIMARY KEY, col2 NUMBER, col3 NUMBER, col4 NUMBER);

   ```

## 创建物化视图时添加主键

#### 注意

为物化视图指定主键后，维护/更新物化视图数据时，如果数据不满足主键约束，将导致视图维护失败。

**示例如下：**

创建名为 `mv0_tbl1` 的物化视图，并指定主键。

```sql
CREATE MATERIALIZED VIEW mv0_tbl1(v_id, v_name, PRIMARY KEY(v_id))
  AS SELECT id, name
     FROM tbl1
     WHERE age >= 20;

```

## 物化视图表选项和分区选项

在创建物化视图时，可以设置表选项，并根据数据特征和访问模式来设计和配置适合的分区选项，以提高查询性能和管理效率。

有关表选项和分区选项的详细参数说明信息，请参见 [CREATE TABLE](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001054349)。

**示例如下：**

创建名为 `mv_tbl1` 的物化视图。指定物化视图的并行度为 `5`，将物化视图按照 `id` 列进行 Hash 分区，并分为 `8` 个分区；将 `tbl1` 表中满足条件 `age >= 20` 的记录作为基表进行查询，并将查询结果作为物化视图的数据。

```sql
CREATE MATERIALIZED VIEW mv_tbl1(id, name)
  PARALLEL 5
  PARTITION BY HASH(id) PARTITIONS 8
  AS SELECT id, name
     FROM tbl1
     WHERE age >= 20;

```

## 物化视图添加索引

#### 说明

在创建物化视图的语句中，不能直接创建索引。要为物化视图创建索引，需要单独使用 [CREATE INDEX](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001054326) 语句。

**示例如下：**

在物化视图 `mv_tbl1` 的 `id` 列上创建名为 `idx_mv_tbl1` 的索引。

```sql
CREATE INDEX idx_mv_tbl1 ON mv_tbl1(id);

```

## 刷新模式（刷新时机）

OceanBase 数据库目前仅支持 `ON DEMAND` 刷新模式，即物化视图在您需要的时候进行刷新。

您还可以通过调用 `DBMS_MVIEW` 包来手动刷新物化视图，也可以在创建物化视图时设置 `START WITH ... NEXT ...` 定时刷新。

更多有关 `DBMS_MVIEW` 的详细信息，请参见 [DBMS_MVIEW 概述](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053958)。

## 刷新方法

OceanBase 数据库物化视图的刷新方法有以下三种：

- 全量刷新（`COMPLETE`）：重新计算整个物化视图的数据，确保视图中的数据与源表完全一致。
 - 增量刷新（`FAST`）：只刷新与源表变化相关的数据，避免对整个视图进行完全计算。

  #### 注意

     - 由于 `REFRESH FAST` 方法利用物化视图日志中的记录信息来确定需要增量刷新的内容，因此在使用增量刷新刷新物化视图时，需要在创建物化视图之前就创建基表的物化视图日志（mlog）。
     - 增量刷新物化视图中使用的列都必须在 mlog 里。有关创建物化视图日志的信息，请参见 [创建物化视图日志](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053741)。
 - 混合刷新（`FORCE`）：默认选项，首先尝试增量刷新，如果增量刷新失败，则执行全量刷新。

更多物化视图刷新的信息，请参见 [刷新物化视图](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053746)。

### 全量刷新

使用 `REFRESH COMPLETE` 子句设置物化视图的刷新方法为全量刷新。

**示例如下：**

创建名为 `mv1_tbl1` 的物化视图。指定物化视图的刷新方法为全量刷新，并且可以根据需要手动触发刷新操作；指定从 `tbl1` 表中选择满足 `age` 大于等于 `20` 的 `id` 和 `name` 列作为物化视图的数据源。

```sql
CREATE MATERIALIZED VIEW mv1_tbl1(id, name)
  REFRESH COMPLETE ON DEMAND
  AS SELECT id, name
     FROM tbl1
     WHERE age >= 20;

```

### 增量刷新

使用 `REFRESH FAST` 子句设置物化视图的刷新方法为增量刷新。

**示例如下：**

1. 在 `tbl3` 表上创建物化视图日志。指定物化视图日志的选项为 `SEQUENCE`，用于指示使用序列号来标识变化的数据，列部分指定了要记录的列，其中包括了 `col2` 和 `col3`。

   ```sql
   CREATE MATERIALIZED VIEW LOG ON tbl3 WITH SEQUENCE (col2, col3) INCLUDING NEW VALUES;

   ```
 2. 创建名为 `mv_tbl3` 的物化视图。指定物化视图的刷新方法为增量刷新，并且可以根据需要手动触发刷新操作；在查询部分，指定了从 `tbl3` 表中按照 `col2` 列进行分组，并计算每个分组中的记录数（`cnt`）、非空 `col3` 列的记录数（`cnt_col3`）和 `col3` 列的总和（`sum_col3`）作为物化视图的结果。

   ```sql
   CREATE MATERIALIZED VIEW mv_tbl3
     REFRESH FAST ON DEMAND
     AS SELECT col2, COUNT(*) cnt, COUNT(col3) cnt_col3, SUM(col3) sum_col3
       FROM tbl3
       GROUP BY col2;

   ```

### 混合刷新（默认选项）

使用 `REFRESH FORCE` 子句设置物化视图的刷新方法为混合刷新。

**示例如下：**

创建名为 `mv2_tbl1` 的物化视图。指定物化视图的刷新方法为混合刷新，并且可以根据需要手动触发刷新操作；指定从 `tbl1` 表中选择满足 `age` 大于等于 `20` 的 `id` 和 `name` 列作为物化视图的数据源。

```sql
CREATE MATERIALIZED VIEW mv2_tbl1(id, name)
  REFRESH FORCE ON DEMAND
  AS SELECT id, name
     FROM tbl1
     WHERE age >= 20;

```

### 永不刷新

使用 `NEVER REFRESH` 子句设置物化视图不需要刷新。即表示物化视图只在创建时进行刷新，并在创建后不允许再次刷新。

**示例如下：**

创建名为 `mv3_tbl1` 的物化视图。指定物化视图的刷新方法为永不刷新；指定从 `tbl1` 表中选择满足 `age` 大于等于 `20` 的 `id` 和 `name` 列作为物化视图的数据源。

```sql
CREATE MATERIALIZED VIEW mv3_tbl1(id, name)
  NEVER REFRESH
  AS SELECT id, name
     FROM tbl1
     WHERE age >= 20;

```

## 自动刷新物化视图

在创建物化视图时，可以通过指定 `START WITH datetime_expr` 和 `NEXT datetime_expr` 子句来为物化视图创建一个后台自动刷新任务。

#### 注意

如果使用了 `NEXT` 子句，刷新计划的时间表达式必须设定在未来的时间点，否则会引发错误。

**示例如下：**

创建名为 `mv_tbl1_tbl2` 的物化视图。指定物化视图的刷新方法为全量刷新；指定物化视图的刷新计划中初始刷新时间为当前日期，之后每隔 `1` 天刷新一次物化视图；在物化视图的查询部分，指定从 `tbl1` 表和 `tbl2` 表中选择 `id`、`name` 和 `notes` 列作为物化视图的数据源，并使用 `t1.id = t2.tbl1_id` 的条件进行连接。

```sql
CREATE MATERIALIZED VIEW mv_tbl1_tbl2
  REFRESH COMPLETE
    START WITH current_date NEXT current_date + 1
  AS SELECT t1.id, t1.name, t2.notes
      FROM tbl1 t1, tbl2 t2
      WHERE t1.id = t2.tbl1_id;

```

## 创建实时物化视图

创建物化视图时，指定 `ENABLE ON QUERY COMPUTATION` 创建实时物化视图。

#### 注意

OceanBase 数据库 Oracle 模式下，创建实时物化视图必须指定刷新方式（`refresh_clause`）。

实时物化视图是一种支持获取实时数据的数据库对象，它通过使用 mlog 的机制来捕获和处理底层基表的更改，确保物化视图中的数据能及时反映最新状态。在执行查询时，实时物化视图会通过在线计算，即时集成这些更改，以向用户展示更新后的数据。这样，即便物化视图没有物理地存储最新的数据，用户仍可以得到实时更新的查询结果。

### 创建实时物化视图注意事项

只有特定类型的物化视图支持指定为实时物化视图，对于不满足条件的物化视图指定实时物化视图时，会导致报错。实时物化视图的要求与增量刷新的物化视图要求是相同的。详细信息，参见 [刷新物化视图](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053746) 中 **增量刷新基本要求** 内容。

**示例如下：**

1. 创建测试表 `tbl4`。

   ```sql
   CREATE TABLE tbl4(col1 INT, col2 INT, col3 INT);

   ```
 2. 创建物化视图日志。

   ```sql
   CREATE MATERIALIZED VIEW LOG ON tbl4 WITH PRIMARY KEY, ROWID, SEQUENCE (col1, col2, col3) INCLUDING NEW VALUES;

   ```
 3. 创建实时物化视图 `mv1_tbl4`。

   ```sql
   CREATE MATERIALIZED VIEW mv1_tbl4
     REFRESH COMPLETE ON DEMAND
     ENABLE ON QUERY COMPUTATION
     AS SELECT col1, count(*) AS cnt
         FROM tbl4
         GROUP BY col1;

   ```
 4. 创建实时物化视图后，可以通过视图 [DBA_MVIEWS](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001051155) 查看物化视图的定位是否为实时物化视图。

   ```sql
   SELECT MVIEW_NAME, ON_QUERY_COMPUTATION FROM sys.DBA_MVIEWS WHERE MVIEW_NAME = 'MV1_TBL4';

   ```

   返回结果如下：

   ```shell
   +------------+----------------------+
   | MVIEW_NAME | ON_QUERY_COMPUTATION |
   +------------+----------------------+
   | MV1_TBL4   | Y                    |
   +------------+----------------------+
   1 row in set

   ```
 5. 查看实时物化视图的执行计划。

   ```sql
   EXPLAIN BASIC SELECT * FROM mv1_tbl4;

   ```

   从下面的执行计划中可以看到，执行期间会同时从物化视图和视图依赖基表的 mlog 读取数据，并对这两部分数据进行计算整合，最终获取实时的物化视图数据。

   返回结果如下：

   ```shell
   +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   | Query Plan                                                                                                                                                                       |
   +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   | =============================================                                                                                                                                    |
   | |ID|OPERATOR                 |NAME          |                                                                                                                                    |
   | ---------------------------------------------                                                                                                                                    |
   | |0 |HASH FULL OUTER JOIN     |              |                                                                                                                                    |
   | |1 |├─SUBPLAN SCAN           |DLT_BASIC_MV$$|                                                                                                                                    |
   | |2 |│ └─HASH GROUP BY        |              |                                                                                                                                    |
   | |3 |│   └─SUBPLAN SCAN       |DLT_T$$       |                                                                                                                                    |
   | |4 |│     └─WINDOW FUNCTION  |              |                                                                                                                                    |
   | |5 |│       └─TABLE FULL SCAN|MLOG$_TBL4    |                                                                                                                                    |
   | |6 |└─TABLE FULL SCAN        |MV1_TBL4      |                                                                                                                                    |
   | =============================================                                                                                                                                    |
   | Outputs & filters:                                                                                                                                                               |
   | -------------------------------------                                                                                                                                            |
   |   0 - output([cast(NVL(MV1_TBL4.COL1, DLT_BASIC_MV$$.COL1), NUMBER(-1, 0))], [cast(CASE WHEN MV1_TBL4.CNT IS NULL THEN DLT_BASIC_MV$$.CNT WHEN DLT_BASIC_MV$$.CNT                |
   |       IS NULL THEN MV1_TBL4.CNT ELSE MV1_TBL4.CNT + DLT_BASIC_MV$$.CNT END, NUMBER(38, 0))]), filter([CASE WHEN MV1_TBL4.CNT IS NULL THEN DLT_BASIC_MV$$.CNT WHEN                |
   |       DLT_BASIC_MV$$.CNT IS NULL THEN MV1_TBL4.CNT ELSE MV1_TBL4.CNT + DLT_BASIC_MV$$.CNT END > cast(0, NUMBER(-1, -85))]), rowset=16                                            |
   |       equal_conds([MV1_TBL4.COL1 <=> DLT_BASIC_MV$$.COL1]), other_conds(nil)                                                                                                     |
   |   1 - output([DLT_BASIC_MV$$.COL1], [DLT_BASIC_MV$$.CNT]), filter(nil), rowset=16                                                                                                |
   |       access([DLT_BASIC_MV$$.COL1], [DLT_BASIC_MV$$.CNT])                                                                                                                        |
   |   2 - output([DLT_T$$.COL1], [T_FUN_SUM(CASE WHEN DLT_T$$.OLD_NEW$$ = cast('N', VARCHAR2(1048576 )) THEN cast(1, NUMBER(-1, -85)) ELSE (T_OP_NEG, cast(1,                        |
   |        NUMBER(-1, -85))) END)]), filter(nil), rowset=16                                                                                                                          |
   |       group([DLT_T$$.COL1]), agg_func([T_FUN_SUM(CASE WHEN DLT_T$$.OLD_NEW$$ = cast('N', VARCHAR2(1048576 )) THEN cast(1, NUMBER(-1, -85)) ELSE (T_OP_NEG,                       |
   |        cast(1, NUMBER(-1, -85))) END)])                                                                                                                                          |
   |   3 - output([DLT_T$$.OLD_NEW$$], [DLT_T$$.COL1]), filter([DLT_T$$.OLD_NEW$$ = cast('N', VARCHAR2(1048576 )) AND DLT_T$$.SEQUENCE$$ = DLT_T$$.MAXSEQ$$ OR                        |
   |       DLT_T$$.OLD_NEW$$ = cast('O', VARCHAR2(1048576 )) AND DLT_T$$.SEQUENCE$$ = DLT_T$$.MINSEQ$$]), rowset=16                                                                   |
   |       access([DLT_T$$.OLD_NEW$$], [DLT_T$$.SEQUENCE$$], [DLT_T$$.MAXSEQ$$], [DLT_T$$.MINSEQ$$], [DLT_T$$.COL1])                                                                  |
   |   4 - output([MLOG$_TBL4.OLD_NEW$$], [MLOG$_TBL4.SEQUENCE$$], [T_FUN_MAX(MLOG$_TBL4.SEQUENCE$$)], [T_FUN_MIN(MLOG$_TBL4.SEQUENCE$$)], [MLOG$_TBL4.COL1]), filter(nil), rowset=16 |
   |       win_expr(T_FUN_MAX(MLOG$_TBL4.SEQUENCE$$)), partition_by([MLOG$_TBL4.M_ROW$$]), order_by(nil), window_type(RANGE), upper(UNBOUNDED PRECEDING), lower(UNBOUNDED             |
   |       FOLLOWING)                                                                                                                                                                 |
   |       win_expr(T_FUN_MIN(MLOG$_TBL4.SEQUENCE$$)), partition_by([MLOG$_TBL4.M_ROW$$]), order_by(nil), window_type(RANGE), upper(UNBOUNDED PRECEDING), lower(UNBOUNDED             |
   |       FOLLOWING)                                                                                                                                                                 |
   |   5 - output([MLOG$_TBL4.M_ROW$$], [MLOG$_TBL4.SEQUENCE$$], [MLOG$_TBL4.OLD_NEW$$], [MLOG$_TBL4.COL1], [ORA_ROWSCN]), filter([cast(ORA_ROWSCN, NUMBER(-1,                        |
   |        -1)) > last_refresh_scn(500069)]), rowset=16                                                                                                                              |
   |       access([MLOG$_TBL4.M_ROW$$], [MLOG$_TBL4.SEQUENCE$$], [MLOG$_TBL4.OLD_NEW$$], [MLOG$_TBL4.COL1], [ORA_ROWSCN]), partitions(p0)                                             |
   |       is_index_back=false, is_global_index=false, filter_before_indexback[false],                                                                                                |
   |       range_key([MLOG$_TBL4.M_ROW$$], [MLOG$_TBL4.SEQUENCE$$]), range(MIN,MIN ; MAX,MAX)always true                                                                              |
   |   6 - output([MV1_TBL4.COL1], [MV1_TBL4.CNT]), filter(nil), rowset=16                                                                                                            |
   |       access([MV1_TBL4.COL1], [MV1_TBL4.CNT]), partitions(p0)                                                                                                                    |
   |       is_index_back=false, is_global_index=false,                                                                                                                                |
   |       range_key([MV1_TBL4.__pk_increment]), range(MIN ; MAX)always true                                                                                                          |
   +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
   40 rows in set

   ```

## 物化视图改写

创建物化视图时，指定 `ENABLE QUERY REWRITE` 开启当前物化视图的自动改写。更多物化视图改写和改写控制的信息，参见 [物化视图查询改写](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053744)。

#### 注意

- 本功能需要物化视图仅包含 `SELECT JOIN` 与 `WHERE` 子句，即 SPJ 查询。对于不满足条件的物化视图，不会报错，但不会被用于改写。
 - OceanBase 数据库 Oracle 模式下，创建支持改写的物化视图时必须指定刷新方式（`refresh_clause`）。

**示例如下：**

1. 创建物化视图 `mv4_tbl1`，并开启自动改写。

   ```sql
   CREATE MATERIALIZED VIEW mv4_tbl1
       NEVER REFRESH
       ENABLE QUERY REWRITE
       AS SELECT *
           FROM tbl1;

   ```
 2. 创建物化视图后，可以通过视图 [DBA_MVIEWS](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001051155) 查看物化视图是否开启自动改写。

   ```sql
   SELECT MVIEW_NAME, REWRITE_ENABLED FROM sys.DBA_MVIEWS WHERE MVIEW_NAME = 'MV4_TBL1';

   ```

   返回结果如下：

   ```shell
   +------------+-----------------+
   | MVIEW_NAME | REWRITE_ENABLED |
   +------------+-----------------+
   | MV4_TBL1   | Y               |
   +------------+-----------------+
   1 row in set

   ```

## 相关文档

- [CREATE MATERIALIZED VIEW](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001054359)
 - [创建物化视图日志](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053741)
 - [查询物化视图](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053747)
 - [删除物化视图](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053743)
 - [刷新物化视图](https://www.oceanbase.com/docs/common-oceanbase-database-cn-1000000001053746)

 上一篇 下一篇 ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
