視圖是存儲在數據庫中的 SELECT 查詢,虛擬表,不存儲物理數據。每次引用時動態執行定義查詢,返回最新結果。本文系統講解視圖語法、三大核心價值 (簡單性、安全性、邏輯獨立性)、可更新條件、物化視圖替代方案及常見坑點。
CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
VIEW view_name [(col_list)]
AS select_statement
[WITH [CASCADED | LOCAL] CHECK OPTION];
ALGORITHM=MERGE:優化器嘗試將視圖查詢合併到外層查詢 (性能最佳),不可包含聚合、DISTINCT、UNION 等。ALGORITHM=TEMPTABLE:先將視圖結果物化到臨時表再連接,支援所有查詢但性能較差。WITH CHECK OPTION:防止通過視圖插入/更新不符合視圖 WHERE 條件的行。GRANT SELECT ON view TO user 只暴露允許的列/行,底層表權限可回收。滿足以下全部條件時,視圖可直接 INSERT/UPDATE/DELETE (最終作用於基表):
SUM, COUNT)、無 DISTINCT、無 GROUP BY、無 HAVING、無 UNION/UNION ALL。FROM 子句、SELECT 列表、WHERE)。JOIN (內連接/外連接均不可更新)。不滿足時視圖為只讀,嘗試寫入報錯 ERROR 1395 (HY000): Can not delete from join view。
CREATE TABLE mv AS SELECT ... + EVENT 定時 TRUNCATE + INSERT 或 REPLACE。AFTER INSERT/UPDATE/DELETE 觸發器維護匯總表。pg_materialized_views (PostgreSQL)、ClickHouse、Apache Druid 等 OLAP 引擎原生支援。| 坑點 | 現象 | 解決 |
|---|---|---|
| 巢狀視圖過深 | 優化器無法合併,退化為 TEMPTABLE,性能指數級下降 | 限制視圖嵌套 ≤ 2 層,核心路徑用 MERGE 算法 |
| 視圖列未顯式別名 | 表達式列名為 expr1,應用層難用 | 定義時顯式 AS alias |
| WITH CHECK OPTION 遺漏 | 應用層繞過業務規則寫入髒數據 | 關鍵視圖必加 WITH CASCADED CHECK OPTION |
| 權限授予視圖而非基表 | 用戶誤以為有表權限實則只有視圖 | 文檔明確標註,審計腳本檢查 |
| 視圖定義使用 SELECT * | 基表加列導致視圖列順序/數量變,應用報錯 | 禁用 SELECT *,顯式列出所有列 |
-- 基表
CREATE TABLE orders (id INT, user_id INT, amount DECIMAL(10,2), status VARCHAR(20));
-- 視圖:用戶只能看自己的訂單
CREATE VIEW v_my_orders AS
SELECT id, amount, status
FROM orders
WHERE user_id = CURRENT_USER(); -- 或 SESSION_USER()
GRANT SELECT ON v_my_orders TO 'app_user'@'%';
REVOKE ALL ON orders FROM 'app_user'@'%';
視圖是「邏輯層封裝」,不是「性能加速器」。濫用視圖隱藏複雜查詢反而會讓優化器失去統計信息、產生劣質計劃。原則:簡單查詢用視圖封裝權限/介面;複雜分析查詢直接寫 SQL 或用物化表。