摘要:本文介紹GaussDB(DWS)的數據庫視圖對象,我們將討論使用數據庫視圖的優點和缺點,以及如何使用系統視圖解決一些問題。
本文分享自華為雲社區《GaussDB(DWS) SQL進階之數據庫對象 - 視圖》,作者:黎明的風 。
(一)視圖概述
當用戶對數據庫中的一張或者多張表的某些字段的組合感興趣,而又不想每次鍵入這些查詢時,用戶就可以定義一個視圖,以便解決這個問題。視圖中列可以來自於表里的不同列,這些列都是用戶所感興趣的數據列。
視圖與表不同,它在物理上不是真實存在的,而是一個虛表。在數據庫里僅存放視圖的定義,而不存放視圖對應的數據。視圖中的這些數據存放在其對應的表中,如果表中的數據發生了變化,從視圖中查詢出的數據也會隨之發生改變。從這個意義來看,視圖就像一個窗口,透過它可以看到數據庫中用戶感興趣的數據及變化。每一次查看視圖或引用視圖的的時候,都會運行一次視圖上的查詢。
用戶可以使用SELECT語句從視圖里查詢數據,對於符合一定約束條件的視圖,還可以使用INSERT、UPDATE、DELETE、MERGE INTO等語句修改視圖對應的基礎表里的數據。視圖在提供操作方便的同時,還可以保障數據庫數據的安全。
(二)數據庫視圖的優點
1.數據庫視圖可以簡化復雜的查詢
數據庫視圖由許多基礎表相關聯的 SQL 語句定義,可以使用數據庫視圖向最終用戶和外部應用程序隱藏底層表的復雜性。通過數據庫視圖,只需要使用簡單的 SQL 語句,不需要編寫具有許多連接的復雜語句。
2.數據庫視圖有助於限制對特定用戶的數據訪問。
如果不希望所有用戶都可以查詢敏感數據,就可以使用數據庫視圖僅向特定用戶組公開非敏感數據。
3.數據庫視圖提供了額外的安全層。
安全性是任何關系數據庫管理系統的重要組成部分,數據庫視圖為數據庫管理系統提供了額外的安全性。數據庫視圖允許創建只讀視圖以向特定用戶公開只讀數據,用戶只能在只讀視圖中檢索數據,但不能對其進行更新。
4.數據庫視圖可以定義計算列。
數據庫表中不應該有計算列,但是數據庫視圖支持有計算列。假設在訂單表中有訂購產品的數量和每個產品的價格列,但是訂單表定義一列來存儲每個訂單的總銷售額。如果有,這樣的數據庫模式也不是一個好的設計。在這種情況下,可以創建一個名為總銷售額的列, 它是計算結果是產品的價格乘以訂購產品的數量。當從數據庫視圖查詢數據時,計算列的數據會動態進行計算。
5.數據庫視圖支持應用兼容性
假設有一個核心數據庫,許多應用程序都在使用它,為了適應新的業務需求,有可能會重新設計數據庫,刪除了一些表並創建了幾個新表,修改表的列名,此時並不希望這些更改影響之前的應用程序。在這種情況下,可以使用與已刪除的舊表相同的表結構創建數據庫視圖。應用程序可以訪問視圖來完成此前功能,這樣就無需對應用程序做任何的修改。
(三)數據庫視圖的缺點
除了上述優點外,使用數據庫視圖有以下幾個缺點:
1.性能可能會較差
從數據庫視圖查詢數據可能會很慢,特別是如果視圖是基於其他視圖創建的。
2.視圖對表結構的依賴
由於視圖時根據數據庫的基礎表創建的,每當更改與視圖關聯的那些表的結構時,也必須更改視圖。
(四)創建視圖的語法
創建視圖需要使用CREATE VIEW語句,其語法格式如下:
CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] VIEW view_name [ ( column_name [, ...] ) ] [ WITH ( {view_option_name [= view_option_value]} [, ... ] ) ] AS query;
語法中的CREATE表示創建,OR REPLACE用於替換已經創建的視圖,TEMP或TEMPORARY表示創建臨時視圖,view_name是要創建的名字字符串,column_name表示屬性列的名字,query表示為視圖提供行和列的SELECT查詢語句或VALUES語句,WITH子句可以為視圖指定一個可選的參數,目前支持的參數為security_barrier,當VIEW試圖提供行級安全時,應使用該參數。
下面是視圖的基本操作示例:
--創建字段spcname為pg_default組成的視圖。 test=# CREATE VIEW myView AS SELECT * FROM pg_tablespace WHERE spcname = 'pg_default'; --查看視圖。 test=# SELECT * FROM myView ; --刪除視圖myView。 test=# DROP VIEW myView;
(五)可更新視圖
在GaussDB(DWS)上,當開啟視圖可更新參數(enable_view_update)后,系統允許對簡單視圖使用INSERT,UPDATE、DELETE和MERGE INTO語句進行更新,滿足以下所有條件的視圖可進行更新:
- 視圖定義的FROM語句中只能有一個普通表,不能是系統表、外表、dfs表、delta表、toast表、錯誤表。
- 視圖中包含可更新的列,這些列是對基礎表可更新列的簡單引用。
- 視圖定義不能包含WITH、DISTINCT、GROUP BY、ORDER BY、FOR UPDATE、FOR SHARE、HAVING、TABLESAMPLE、LIMIT、OFFSET子句。
- 視圖定義不能包含UNION、INTERSECT、EXCEPT集合操作。
- 視圖定義的選擇列表不能包含聚集函數、窗口函數、返回集合的函數。
- 視圖上不能有觸發時機為INSTEAD OF的觸發器。
- 視圖定義不能包含子鏈接。
- 視圖定義不能包含屬性為VOLATILE的函數(函數值可以在一次表掃描內改變的函數)
- 視圖定義不能對表的分布鍵所在列起別名,或將普通列起別名為分布鍵列名。
- 視圖更新操作中包含RETURNING子句時,視圖定義中的列只能來自於基礎表。
如果可更新的視圖定義包含WHERE條件,則該條件將會限制UPDATE和DELETE語句修改基礎表上的行。如果UPDATE語句更改行后不再滿足WHERE條件,更新后通過視圖將無法查詢到。類似地如果INSERT命令插入了不滿足WHERE條件的數據,插入后通過視圖將無法查詢到。在視圖上執行插入、更新或刪除的用戶必須在視圖和表上具有相應的插入、更新或刪除權限。
以下是對可更新視圖的進行更新操作的例子:
test=# create view v1 as select * from t1; CREATE VIEW test=# insert into v1 values(1, 2, 3); INSERT 0 1 test=# delete from v1 where a = 1; DELETE 3 test=# update v1 set b = 100 where a = 2; UPDATE 2 test=# delete from v1 where a = 2; DELETE 2
以下是可更新視圖執行MERGE INTO語句的例子:
test=# CREATE TABLE products(product_id INTEGER, product_name VARCHAR2(60), category VARCHAR2(60)); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'product_id' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE test=# CREATE VIEW products_view AS SELECT * FROM products; CREATE VIEW test=# CREATE TABLE newproducts(product_id INTEGER, product_name VARCHAR2(60), category VARCHAR2(60)); NOTICE: The 'DISTRIBUTE BY' clause is not specified. Using 'product_id' as the distribution column by default. HINT: Please use 'DISTRIBUTE BY' clause to specify suitable data distribution column. CREATE TABLE test=# CREATE VIEW newproducts_view AS SELECT * FROM newproducts; CREATE VIEW test=# INSERT INTO products_view VALUES (1501, 'vivitar 35mm', 'electrncs'); INSERT 0 1 test=# INSERT INTO products_view VALUES (1502, 'olympus is50', 'electrncs'); INSERT 0 1 test=# INSERT INTO products_view VALUES (1600, 'play gym', 'toys'); INSERT 0 1 test=# INSERT INTO products_view VALUES (1601, 'lamaze', 'toys'); INSERT 0 1 test=# INSERT INTO products_view VALUES (1666, 'harry potter', 'dvd'); INSERT 0 1 test=# INSERT INTO newproducts_view VALUES (1502, 'olympus camera', 'electrncs'); INSERT 0 1 test=# INSERT INTO newproducts_view VALUES (1601, 'lamaze', 'toys'); INSERT 0 1 test=# INSERT INTO newproducts_view VALUES (1666, 'harry potter', 'toys'); INSERT 0 1 test=# INSERT INTO newproducts_view VALUES (1700, 'wait interface', 'books'); INSERT 0 1 MERGE INTO products_view p USING newproducts_view np ON (p.product_id = np.product_id) WHEN MATCHED THEN UPDATE SET p.product_name = np.product_name, p.category = np.category WHERE p.product_name != 'play gym' WHEN NOT MATCHED THEN INSERT VALUES (np.product_id, np.product_name, np.category) WHERE np.category = 'books'; MERGE 4 test=# SELECT * FROM products_view ORDER BY 1; product_id | product_name | category ------------+----------------+----------- 1501 | vivitar 35mm | electrncs 1502 | olympus camera | electrncs 1600 | play gym | toys 1601 | lamaze | toys 1666 | harry potter | toys 1700 | wait interface | books (6 rows)
(六)GaussDB(DWS)常用系統視圖
GaussDB(DWS)還提供了許多視圖用於展示數據庫的內部狀態,以下幾個視圖,在定位故障時會經常使用。
- pg_stat_activity:用於查詢當前實例上各個Session的狀態
test=# select datid, pid, application_name, query_id, query from pg_stat_activity; datid | pid | application_name | query_id | query -------+-----------------+--------------------+--------------------+----------------------------------------------------------------------------- 14950 | 139706178189056 | JobScheduler | 0 | 14950 | 139706093266688 | WDRSnapshot | 0 | 14950 | 139706040301312 | workload | 100768041662414941 | WLM fetch collect info from data nodes 14950 | 139705995208448 | CalculateSpaceInfo | 0 | 14950 | 139705978427136 | WorkloadMonitor | 100768041662414940 | WLM monitor update and verify local info 14950 | 139705953277696 | WLMArbiter | 0 | WLM arbiter sync info by CCN and CNs 16390 | 139705917097728 | gsql | 100768041662414942 | select datid, pid, application_name, query_id, query from pg_stat_activity; (7 rows)
- pg_thread_wait_status:用於查詢該實例上各個線程的等待事件
test=# select * from pg_thread_wait_status; node_name | db_name | thread_name | query_id | tid | lwtid | ptid | tlevel | smpid | wait_status | wait_event --------------+----------+--------------------+--------------------+-----------------+--------+------+--------+-------+-------------+------------ coordinator1 | postgres | JobScheduler | 0 | 139706178189056 | 128830 | | 0 | 0 | none | coordinator1 | postgres | WDRSnapshot | 0 | 139706093266688 | 128834 | | 0 | 0 | none | coordinator1 | postgres | workload | 100768041662415325 | 139706040301312 | 128837 | | 0 | 0 | none | coordinator1 | postgres | CalculateSpaceInfo | 0 | 139705995208448 | 128838 | | 0 | 0 | none | coordinator1 | postgres | WorkloadMonitor | 100768041662415251 | 139705978427136 | 128839 | | 0 | 0 | none | coordinator1 | postgres | WLMArbiter | 0 | 139705953277696 | 128840 | | 0 | 0 | none | coordinator1 | test | gsql | 100768041662415326 | 139705917097728 | 129109 | | 0 | 0 | none | coordinator1 | | Background writer | 0 | 139706242688768 | 128826 | | 0 | 0 | none | coordinator1 | | CheckPointer | 0 | 139706262091520 | 128825 | | 0 | 0 | none | coordinator1 | | Wal Writer | 0 | 139706225907456 | 128827 | | 0 | 0 | none | coordinator1 | | TwoPhase Cleaner | 0 | 139706076485376 | 128835 | | 0 | 0 | none | coordinator1 | | LWLock Monitor | 0 | 139706057082624 | 128836 | | 0 | 0 | none | (12 rows)
- pg_locks:用於查詢當前實例上的鎖狀態
test=# select locktype, database, relation, pid, mode from pg_locks; locktype | database | relation | pid | mode ------------+----------+----------+-----------------+----------------- relation | 16390 | 11800 | 139705917097728 | AccessShareLock virtualxid | | | 139705917097728 | ExclusiveLock virtualxid | | | 139705953277696 | ExclusiveLock virtualxid | | | 139705978427136 | ExclusiveLock virtualxid | | | 139706040301312 | ExclusiveLock (5 rows)
- pgxc_node:用於顯示集群中所有實例的IP和端口號
test=# select node_name, node_type, node_port, node_host from pgxc_node; node_name | node_type | node_port | node_host --------------+-----------+-----------+----------- coordinator1 | C | 56200 | localhost datanode1 | D | 56201 | localhost datanode2 | D | 56202 | localhost datanode3 | D | 56203 | localhost datanode4 | D | 56204 | localhost (5 rows)
想了解GuassDB(DWS)更多信息,歡迎微信搜索“GaussDB DWS”關注微信公眾號,和您分享最新最全的PB級數倉黑科技,后台還可獲取眾多學習資料哦~