
# 使用DWS视图重建功能实现视图解耦以提升开发效率
为了解决因存在视图和表依赖而无法单独修改表对象的问题，DWS实现了视图的解耦与重建功能。本文重点介绍视图自动重建功能的使用场景与使用方法。
#### 场景介绍
DWS使用对象标识符（oid）来保存对象之间的引用关系，这使得视图在定义的时候就绑定了其依赖的数据库对象的oid，不管视图名称怎么改变，都不会改变这层依赖关系。如果要对基表进行一些字段修改，会因为与视图字段存在强绑定而报错。如果要删除某个表字段或整个表，就需要连同其关联的视图一起使用cascade关键字删除，表字段删除完成或表重建后再依次重建各级视图，给用户的使用增加了很大的工作量，导致易用性较差。
为了解决这一问题，DWS在8.1.0集群版本实现了视图的解耦，使得存在视图依赖的基表或其他数据库对象（视图、同义词、函数、表字段）可以单独删除，而其对应对象上关联的依赖视图依然存在，在基表重建后，可以通过ALTER VIEW REBUILD命令重建依赖关系。而8.1.1集群版本在此基础上又实现了自动重建，可以无感知自动重建依赖关系，开启自动重建后会有锁冲突，因此不建议用户开启自动重建。8.2.1.200集群版本在此基础上取消了无感知自动重建，改为本地自动重建，即视图自动重建后未更新系统表，此时，无效视图仍旧无效，但是无效视图依然可以进行DML操作，如果需要将视图元数据刷新为有效状态，依然需要执行ALTER VIEW REBUILD操作。
#### 使用方法
1. 在[DWS控制台](https://console.huaweicloud.com/dws)上创建集群，具体操作步骤请参考[创建DWS存算一体集群](https://support.huaweicloud.com/mgtg-dws/dws_01_0019.html)。
2. 打开GUC参数view_independent。 
   视图解耦功能由GUC参数view_independent进行控制，默认关闭。使用时需要用户手动打开，可登录[DWS控制台](https://console.huaweicloud.com/dws)后，单击集群名称，进入"集群详情"页面，单击"参数修改"页签，并在"参数列表"模块搜索view_independent参数，修改后保存。
   ![](https://support.huaweicloud.com/bestpractice-dws/figure/zh-cn_image_0000001609081245.png "点击放大")
   
   
   
3. 执行以下命令，使用gsql客户端连接DWS集群中的数据库，其中password为用户创建集群时自定义的密码。 
   ```
   gsql -d gaussdb -p 8000 -h 192.168.0.86 -U dbadmin -W password -r
   ```
   显示如下信息表示gsql工具已经连接成功：
   ```
   gaussdb=>
   ```
   
   
4. 创建示例表t1并插入数据。 
   ```
   SET current_schema='public';
   CREATE TABLE t1 (a int, b int, c char(10)) DISTRIBUTE BY HASH (a);
   INSERT INTO t1 VALUES(1,1,'a'),(2,2,'b');
   ```
   
   
5. 创建视图v1依赖表t1，创建视图v11依赖视图v1。查询视图v11。 
   ```
   CREATE VIEW v1 AS SELECT a, b FROM t1;
   CREATE VIEW v11 AS SELECT a FROM v1;
   SELECT * FROM v11;
    a
   ---
    1
    2
   (2 rows)
   ```
   
   
6. 删除表t1后，查询视图v11会因表t1不存在而报错，但视图是依旧存在的。 
   DWS提供GS_VIEW_INVALID视图查询当前用户可见的所有不可用的视图。如果该视图依赖的基础表或函数或同义词存在异常，该视图validtype列显示为"invalid"。
   ```
   DROP TABLE t1; 
   SELECT * FROM v11;
   ERROR:  relation "public.t1" does not exist  
   SELECT * FROM gs_view_invalid;
     oid   | schemaname | viewname | viewowner |         definition          | validtype
   --------+------------+----------+-----------+-----------------------------+-----------
    213563 | public     | v1       | dbadmin   | SELECT a, b FROM public.t1; | invalid
    213567 | public     | v11      | dbadmin   | SELECT a FROM public.v1;    | invalid
   (2 rows)
   ```
   
   
7. 8.2.1.200之前的历史版本集群，重建表t1后，视图自动重建。视图只有在使用时才能自动刷新。 
   ```
   CREATE TABLE t1 (a int, b int, c char(10)) DISTRIBUTE BY HASH (a);
   INSERT INTO t1 VALUES(1,1,'a'),(2,2,'b');
     
   SELECT * from v1;
    a | b
   ---+---
    1 | 1
    2 | 2
   (2 rows)
   SELECT * FROM gs_view_invalid;
     oid   | schemaname | viewname | viewowner |        definition        | validtype
   --------+------------+----------+-----------+--------------------------+-----------
    213567 | public     | v11      | dbadmin   | SELECT a FROM public.v1; | invalid
   (1 row)
   SELECT * from v11;
    a 
   ---
    1 
    2 
   (2 rows)
   SELECT * FROM gs_view_invalid;
    oid | schemaname | viewname | viewowner | definition | validtype
   -----+------------+----------+-----------+------------+-----------
   (0 rows)
   ```
   
   
8. 8.2.1.200及之后的版本集群，重建表t1后，视图不会自动重建，执行ALTER VIEW REBUILD操作后视图才能自动刷新。 
   ```
   CREATE TABLE t1 (a int, b int, c char(10)) DISTRIBUTE BY HASH (a);
   INSERT INTO t1 VALUES(1,1,'a'),(2,2,'b');
     
   SELECT * from v1;
    a | b
   ---+---
    1 | 1
    2 | 2
   (2 rows)
   SELECT * FROM gs_view_invalid;
     oid   | schemaname | viewname | viewowner |          definition         | validtype
   --------+------------+----------+-----------+-----------------------------+-----------
    213563 | public     | v1       | dbadmin   | SELECT a, b FROM public.t1; | invalid
    213567 | public     | v11      | dbadmin   | SELECT a FROM public.v1;    | invalid
   (1 row)
   ALTER VIEW ONLY v1 REBUILD;
   SELECT * FROM gs_view_invalid;
     oid   | schemaname | viewname | viewowner |        definition        | validtype
   --------+------------+----------+-----------+--------------------------+-----------
    213567 | public     | v11      | dbadmin   | SELECT a FROM public.v1; | invalid
   (1 rows)
   ```
   
   
 
