opengauss教程FG018-openGauss视图与物化视图
目录大纲
Part01-基础概念与理论知识
1.1 视图概述
视图是数据库中基于SQL查询结果的虚拟表,了解视图的概念和使用方法对于数据库的操作和管理至关重要。风哥教程参考opengauss官方文档,视图具有以下特点:
- 虚拟表:视图是基于查询结果的虚拟表,不存储实际数据
- 简化查询:视图可以简化复杂的查询,提高查询的可读性和可维护性
- 权限控制:视图可以控制用户对数据的访问权限,只显示用户需要的数据
- 数据安全性:视图可以隐藏敏感数据,提高数据安全性
1.2 物化视图概述
物化视图是一种特殊的视图,它存储查询结果的实际数据,了解物化视图的概念和使用方法对于数据库的性能优化至关重要:
- 存储数据:物化视图存储查询结果的实际数据,而不是虚拟表
- 提高查询性能:物化视图可以提高复杂查询的性能,避免重复计算
- 定期刷新:物化视图需要定期刷新以保持数据的最新状态
- 空间开销:物化视图会占用额外的存储空间
1.3 视图与物化视图的区别
视图与物化视图的主要区别:
- 存储方式:
- 视图:不存储实际数据,只是一个查询定义
- 物化视图:存储查询结果的实际数据
- 查询性能:
- 视图:每次查询都需要重新执行查询语句
- 物化视图:直接使用存储的数据,查询性能更高
- 数据一致性:
- 视图:总是与基础表保持一致
- 物化视图:需要定期刷新才能保持与基础表的一致
- 空间开销:
- 视图:几乎不占用存储空间
- 物化视图:占用额外的存储空间
风哥提示:合理使用视图和物化视图可以提高数据库的查询性能和可维护性。
Part02-生产环境规划与建议
2.1 视图设计规划
生产环境视图设计规划
- 命名规范:
- 使用v_前缀,如v_fgedu_employee
- 使用小写字母和下划线
- 包含表名和视图的用途
- 设计原则:
- 简化复杂查询
- 控制数据访问权限
- 提高查询的可读性和可维护性
- 使用场景:
- 简化复杂的连接查询
- 控制用户对数据的访问权限
- 隐藏敏感数据
风哥提示:
2.2 物化视图设计规划
生产环境的物化视图设计规划建议:
- 命名规范:
- 使用mv_前缀,如mv_fgedu_sales_summary
- 使用小写字母和下划线
- 包含表名和物化视图的用途
- 设计原则:
- 选择频繁执行的复杂查询
- 考虑数据刷新的频率
- 评估存储空间的需求
- 使用场景:
- 报表查询
- 数据分析
- 数据汇总
学习交流加群风哥微信: itpux-com
2.3 性能优化建议
视图与物化视图的性能优化建议:
- 视图优化:
- 避免在视图中使用复杂的查询
- 合理使用索引
- 避免嵌套视图
- 物化视图优化:
- 选择合适的刷新策略
- 合理设置刷新频率
- 使用增量刷新减少资源消耗
- 资源管理:
- 监控物化视图的存储空间
- 定期维护物化视图
- 合理设置物化视图的刷新时间
Part03-生产环境项目实施方案
3.1 视图创建与管理
# 创建视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss
Password for user opengauss:
gsql ((openGauss 5.0.0 build 12345) compiled at 2024-01-01 00:00:00)
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type “help” for help.
fgedudb=# CREATE OR REPLACE VIEW v_fgedu_employee AS
fgedudb-# SELECT e.id, e.name, e.age, d.name as department, e.salary
fgedudb-# FROM fgedu_employee e
学习交流加群风哥QQ113257174
fgedudb-# JOIN fgedu_department d ON e.dept_id = d.id;
CREATE VIEW
# 查询视图
fgedudb=# SELECT * FROM v_fgedu_employee;
id | name | age | department | salary
—-+———-+—–+————+——–
1 | Zhang San | 30 | IT | 9300.00
2 | Li Si | 25 | IT | 6600.00
3 | Wang Wu | 35 | HR | 7000.00
4 | Zhao Liu | 40 | Finance | 9000.00
(4 rows)
# 删除视图
fgedudb=# DROP VIEW IF EXISTS v_fgedu_employee;
DROP VIEW
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss
Password for user opengauss:
gsql ((openGauss 5.0.0 build 12345) compiled at 2024-01-01 00:00:00)
Non-SSL connection (SSL connection is recommended when requiring high-security)
Type “help” for help.
fgedudb=# CREATE OR REPLACE VIEW v_fgedu_employee AS
fgedudb-# SELECT e.id, e.name, e.age, d.name as department, e.salary
fgedudb-# FROM fgedu_employee e
学习交流加群风哥QQ113257174
fgedudb-# JOIN fgedu_department d ON e.dept_id = d.id;
CREATE VIEW
# 查询视图
fgedudb=# SELECT * FROM v_fgedu_employee;
id | name | age | department | salary
—-+———-+—–+————+——–
1 | Zhang San | 30 | IT | 9300.00
2 | Li Si | 25 | IT | 6600.00
3 | Wang Wu | 35 | HR | 7000.00
4 | Zhao Liu | 40 | Finance | 9000.00
(4 rows)
# 删除视图
fgedudb=# DROP VIEW IF EXISTS v_fgedu_employee;
DROP VIEW
3.2 物化视图创建与管理
# 创建物化视图
fgedudb=# CREATE MATERIALIZED VIEW mv_fgedu_department_summary AS
fgedudb-# SELECT d.id, d.name, COUNT(e.id) as employee_count, AVG(e.salary) as avg_salary
fgedudb-# FROM fgedu_department d
fgedudb-# LEFT JOIN fgedu_employee e ON d.id = e.dept_id
fgedudb-# GROUP BY d.id, d.name;
CREATE MATERIALIZED VIEW
# 查询物化视图
fgedudb=# SELECT * FROM mv_fgedu_department_summary;
id | name | employee_count | avg_salary
—-+———-+—————-+———————
1 | IT | 2 | 7950.00000000000000
2 | HR | 1 | 7000.00000000000000
3 | Finance | 1 | 9000.00000000000000
(3 rows)
# 刷新物化视图
fgedudb=# REFRESH MATERIALIZED VIEW mv_fgedu_department_summary;
REFRESH MATERIALIZED VIEW
# 删除物化视图
fgedudb=# DROP MATERIALIZED VIEW IF EXISTS mv_fgedu_department_summary;
DROP MATERIALIZED VIEW
fgedudb=# CREATE MATERIALIZED VIEW mv_fgedu_department_summary AS
fgedudb-# SELECT d.id, d.name, COUNT(e.id) as employee_count, AVG(e.salary) as avg_salary
fgedudb-# FROM fgedu_department d
fgedudb-# LEFT JOIN fgedu_employee e ON d.id = e.dept_id
fgedudb-# GROUP BY d.id, d.name;
CREATE MATERIALIZED VIEW
# 查询物化视图
fgedudb=# SELECT * FROM mv_fgedu_department_summary;
id | name | employee_count | avg_salary
—-+———-+—————-+———————
1 | IT | 2 | 7950.00000000000000
2 | HR | 1 | 7000.00000000000000
3 | Finance | 1 | 9000.00000000000000
(3 rows)
# 刷新物化视图
fgedudb=# REFRESH MATERIALIZED VIEW mv_fgedu_department_summary;
REFRESH MATERIALIZED VIEW
# 删除物化视图
fgedudb=# DROP MATERIALIZED VIEW IF EXISTS mv_fgedu_department_summary;
DROP MATERIALIZED VIEW
更多视频教程www.fgedu.net.cn
3.3 权限管理
# 授予视图权限
fgedudb=# GRANT SELECT ON v_fgedu_employee TO fgedu;
GRANT
fgedudb=# GRANT SELECT ON mv_fgedu_department_summary TO fgedu;
GRANT
# 撤销视图权限
fgedudb=# REVOKE SELECT ON v_fgedu_employee FROM fgedu;
REVOKE
fgedudb=# GRANT SELECT ON v_fgedu_employee TO fgedu;
GRANT
fgedudb=# GRANT SELECT ON mv_fgedu_department_summary TO fgedu;
GRANT
# 撤销视图权限
fgedudb=# REVOKE SELECT ON v_fgedu_employee FROM fgedu;
REVOKE
Part04-生产案例与实战讲解
4.1 视图实战
# 创建员工信息视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE OR REPLACE VIEW v_fgedu_employee_info AS SELECT e.id, e.name, e.age, d.name as department, e.salary, e.hire_date FROM fgedu_employee e JOIN fgedu_department d ON e.dept_id = d.id;
“
Password for user opengauss:
CREATE VIEW
# 查询视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM v_fgedu_employee_info WHERE department = ‘IT’;
“
Password for user opengauss:
id | name | age | department | salary | hire_date
—-+———-+—–+————+——–+————-
1 | Zhang San | 30 | IT | 9300.00 | 2024-01-01
2 | Li Si | 25 | IT | 6600.00 | 2024-01-01
(2 rows)
# 创建部门统计视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE OR REPLACE VIEW v_fgedu_dept_stats AS SELECT d.name as department, COUNT(e.id) as employee_count, AVG(e.salary) as avg_salary, MAX(e.salary) as max_salary, MIN(e.salary) as min_salary FROM fgedu_department d LEFT JOIN fgedu_employee e ON d.id = e.dept_id GROUP BY d.name;
“
Password for user opengauss:
CREATE VIEW
# 查询部门统计视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM v_fgedu_dept_stats;
“
Password for user opengauss:
department | employee_count | avg_salary | max_salary | min_salary
————+—————-+———————+————+————
IT | 2 | 7950.00000000000000 | 9300.00 | 6600.00
HR | 1 | 7000.00000000000000 | 7000.00 | 7000.00
更多学习教程公众号风哥教程itpux_com
Finance | 1 | 9000.00000000000000 | 9000.00 | 9000.00
(3 rows)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE OR REPLACE VIEW v_fgedu_employee_info AS SELECT e.id, e.name, e.age, d.name as department, e.salary, e.hire_date FROM fgedu_employee e JOIN fgedu_department d ON e.dept_id = d.id;
“
Password for user opengauss:
CREATE VIEW
# 查询视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM v_fgedu_employee_info WHERE department = ‘IT’;
“
Password for user opengauss:
id | name | age | department | salary | hire_date
—-+———-+—–+————+——–+————-
1 | Zhang San | 30 | IT | 9300.00 | 2024-01-01
2 | Li Si | 25 | IT | 6600.00 | 2024-01-01
(2 rows)
# 创建部门统计视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE OR REPLACE VIEW v_fgedu_dept_stats AS SELECT d.name as department, COUNT(e.id) as employee_count, AVG(e.salary) as avg_salary, MAX(e.salary) as max_salary, MIN(e.salary) as min_salary FROM fgedu_department d LEFT JOIN fgedu_employee e ON d.id = e.dept_id GROUP BY d.name;
“
Password for user opengauss:
CREATE VIEW
# 查询部门统计视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM v_fgedu_dept_stats;
“
Password for user opengauss:
department | employee_count | avg_salary | max_salary | min_salary
————+—————-+———————+————+————
IT | 2 | 7950.00000000000000 | 9300.00 | 6600.00
HR | 1 | 7000.00000000000000 | 7000.00 | 7000.00
更多学习教程公众号风哥教程itpux_com
Finance | 1 | 9000.00000000000000 | 9000.00 | 9000.00
(3 rows)
4.2 物化视图实战
# 创建销售汇总物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE MATERIALIZED VIEW mv_fgedu_sales_summary AS SELECT p.category, COUNT(o.id) as order_count, SUM(o.quantity) as total_quantity, SUM(p.price * o.quantity) as total_amount FROM fgedu_product p JOIN fgedu_order o ON p.id = o.product_id GROUP BY p.category;
“
Password for user opengauss:
CREATE MATERIALIZED VIEW
# 查询物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 3 | 6 | 22499.94
Furniture | 2 | 3 | 1899.97
(2 rows)
# 插入新订单
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “INSERT INTO fgedu_order (customer_name, product_id, quantity) VALUES (‘Frank’, 1, 1);
“
Password for user opengauss:
INSERT 0 1
# 查询物化视图(数据未更新)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 3 | 6 | 22499.94
Furniture | 2 | 3 | 1899.97
(2 rows)
from DB视频:www.itpux.com
# 刷新物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “REFRESH MATERIALIZED VIEW mv_fgedu_sales_summary;”
Password for user opengauss:
REFRESH MATERIALIZED VIEW
# 查询物化视图(数据已更新)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 4 | 7 | 27899.93
Furniture | 2 | 3 | 1899.97
(2 rows)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE MATERIALIZED VIEW mv_fgedu_sales_summary AS SELECT p.category, COUNT(o.id) as order_count, SUM(o.quantity) as total_quantity, SUM(p.price * o.quantity) as total_amount FROM fgedu_product p JOIN fgedu_order o ON p.id = o.product_id GROUP BY p.category;
“
Password for user opengauss:
CREATE MATERIALIZED VIEW
# 查询物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 3 | 6 | 22499.94
Furniture | 2 | 3 | 1899.97
(2 rows)
# 插入新订单
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “INSERT INTO fgedu_order (customer_name, product_id, quantity) VALUES (‘Frank’, 1, 1);
“
Password for user opengauss:
INSERT 0 1
# 查询物化视图(数据未更新)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 3 | 6 | 22499.94
Furniture | 2 | 3 | 1899.97
(2 rows)
from DB视频:www.itpux.com
# 刷新物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “REFRESH MATERIALIZED VIEW mv_fgedu_sales_summary;”
Password for user opengauss:
REFRESH MATERIALIZED VIEW
# 查询物化视图(数据已更新)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “SELECT * FROM mv_fgedu_sales_summary;
“
Password for user opengauss:
category | order_count | total_quantity | total_amount
————-+————-+—————-+————–
Electronics | 4 | 7 | 27899.93
Furniture | 2 | 3 | 1899.97
(2 rows)
4.3 性能优化实战
# 创建带索引的物化视图
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE MATERIALIZED VIEW mv_fgedu_employee_stats AS SELECT dept_id, COUNT(*) as employee_count, AVG(salary) as avg_salary, MAX(salary) as max_salary, MIN(salary) as min_salary FROM fgedu_employee GROUP BY dept_id;
“
Password for user opengauss:
CREATE MATERIALIZED VIEW
# 为物化视图创建索引
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE INDEX idx_mv_fgedu_employee_stats_dept_id ON mv_fgedu_employee_stats(dept_id);
“
Password for user opengauss:
CREATE INDEX
# 测试物化视图查询性能
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “EXPLAIN ANALYZE SELECT * FROM mv_fgedu_employee_stats WHERE dept_id = 1;
“
Password for user opengauss:
QUERY PLAN
————————————————————————————–
Index Scan using idx_mv_fgedu_employee_stats_dept_id on mv_fgedu_employee_stats (cost=0.29..8.30 rows=1 width=28)
Index Cond: (dept_id = 1)
Execution Time: 0.087 ms
(3 rows)
# 测试直接查询性能
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “EXPLAIN ANALYZE SELECT dept_id, COUNT(*) as employee_count, AVG(salary) as avg_salary, MAX(salary) as max_salary, MIN(salary) as min_salary FROM fgedu_employee WHERE dept_id = 1 GROUP BY dept_id;
“
Password for user opengauss:
QUERY PLAN
————————————————————————————–
HashAggregate (cost=8.32..8.33 rows=1 width=28)
Group Key: dept_id
-> Index Scan using idx_fgedu_employee_dept on fgedu_employee (cost=0.29..8.31 rows=1 width=12)
Index Cond: (dept_id = 1)
Execution Time: 0.123 ms
(4 rows)
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE MATERIALIZED VIEW mv_fgedu_employee_stats AS SELECT dept_id, COUNT(*) as employee_count, AVG(salary) as avg_salary, MAX(salary) as max_salary, MIN(salary) as min_salary FROM fgedu_employee GROUP BY dept_id;
“
Password for user opengauss:
CREATE MATERIALIZED VIEW
# 为物化视图创建索引
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “CREATE INDEX idx_mv_fgedu_employee_stats_dept_id ON mv_fgedu_employee_stats(dept_id);
“
Password for user opengauss:
CREATE INDEX
# 测试物化视图查询性能
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “EXPLAIN ANALYZE SELECT * FROM mv_fgedu_employee_stats WHERE dept_id = 1;
“
Password for user opengauss:
QUERY PLAN
————————————————————————————–
Index Scan using idx_mv_fgedu_employee_stats_dept_id on mv_fgedu_employee_stats (cost=0.29..8.30 rows=1 width=28)
Index Cond: (dept_id = 1)
Execution Time: 0.087 ms
(3 rows)
# 测试直接查询性能
[opengauss@fgedu.net.cn ~]$ gsql -d fgedudb -U opengauss -c “EXPLAIN ANALYZE SELECT dept_id, COUNT(*) as employee_count, AVG(salary) as avg_salary, MAX(salary) as max_salary, MIN(salary) as min_salary FROM fgedu_employee WHERE dept_id = 1 GROUP BY dept_id;
“
Password for user opengauss:
QUERY PLAN
————————————————————————————–
HashAggregate (cost=8.32..8.33 rows=1 width=28)
Group Key: dept_id
-> Index Scan using idx_fgedu_employee_dept on fgedu_employee (cost=0.29..8.31 rows=1 width=12)
Index Cond: (dept_id = 1)
Execution Time: 0.123 ms
(4 rows)
Part05-风哥经验总结与分享
5.1 视图与物化视图使用技巧
- 视图使用技巧:
- 使用视图简化复杂的查询
- 使用视图控制用户对数据的访问权限
- 使用视图隐藏敏感数据
- 避免在视图中使用复杂的逻辑
- 物化视图使用技巧:
- 使用物化视图提高复杂查询的性能
- 选择合适的刷新策略
- 为物化视图创建适当的索引
- 定期刷新物化视图以保持数据的一致性
- 选择原则:
- 对于简单查询,使用视图
- 对于复杂查询且数据不经常变化,使用物化视图
- 对于实时性要求高的数据,使用视图
- 对于性能要求高的报表查询,使用物化视图
5.2 性能优化要点
- 视图优化:
- 避免在视图中使用复杂的查询
- 合理使用索引
- 避免嵌套视图
- 定期分析视图的使用情况
- 物化视图优化:
- 选择合适的刷新策略
- 合理设置刷新频率
- 使用增量刷新减少资源消耗
- 为物化视图创建适当的索引
- 资源管理:
- 监控物化视图的存储空间
- 定期维护物化视图
- 合理设置物化视图的刷新时间
- 避免在高峰期刷新物化视图
5.3 常见问题与解决方案
常见视图与物化视图问题及解决方法
- 问题1:视图查询性能慢
- 症状:视图查询执行时间长
- 解决方案:优化视图的底层查询,合理使用索引,考虑使用物化视图
- 问题2:物化视图数据不一致
- 症状:物化视图中的数据与基础表不一致
- 解决方案:定期刷新物化视图,设置合适的刷新策略
- 问题3:物化视图占用空间过大
- 症状:物化视图占用过多的存储空间
- 解决方案:定期清理物化视图,优化物化视图的设计
- 问题4:视图权限不足
- 症状:用户无法访问视图
- 解决方案:授予用户对视图的适当权限
风哥提示:视图与物化视图是数据库中重要的对象,合理使用视图和物化视图可以提高数据库的查询性能和可维护性。在生产环境中,应该根据具体的业务需求选择合适的视图类型,定期维护和优化视图,确保数据库的稳定运行和高性能。
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
