-- 创建一个活跃用户视图,只显示状态为active的用户 CREATEVIEW active_users AS SELECT id, -- 用户ID username, -- 用户名 email, -- 邮箱 age, -- 年龄 create_time -- 创建时间 FROM users WHERE status ='active'-- 只选择活跃用户 ORDERBY create_time DESC; -- 按创建时间降序排列
-- 创建一个复杂的统计视图,展示用户年龄分布 CREATEVIEW user_age_stats AS SELECT CASE WHEN age <20THEN'未成年'-- 年龄分组:小于20岁 WHEN age BETWEEN20AND30THEN'青年'-- 20-30岁 WHEN age BETWEEN31AND50THEN'中年'-- 31-50岁 ELSE'老年'-- 大于50岁 ENDAS age_group, -- 年龄组别 COUNT(*) AS user_count, -- 该年龄组用户数量 AVG(age) AS avg_age -- 该年龄组平均年龄 FROM users WHERE status ='active'-- 只统计活跃用户 GROUPBY age_group -- 按年龄组分组 ORDERBY user_count DESC; -- 按用户数量降序排列
二、核心区别分析
(一)存储方式差异
1. 表的存储特点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
-- 表占用实际的磁盘空间,存储真实数据 -- 查看表的存储信息 SELECT table_name, -- 表名 table_rows, -- 行数 data_length, -- 数据大小(字节) index_length, -- 索引大小(字节) (data_length + index_length) AS total_size -- 总大小 FROM information_schema.tables WHERE table_schema ='your_database'-- 指定数据库名 AND table_name ='users'; -- 指定表名
-- 重新计算并插入新数据 INSERT INTO materialized_user_stats SELECT DATE(create_time) ASdate, COUNT(*) AS new_users, AVG(age) AS avg_age FROM users GROUPBYDATE(create_time); END// DELIMITER ;
物化视图性能测试结果:
测试场景:查询每日用户注册统计(基于100万用户数据)
查询方式
首次查询时间
后续查询时间
存储空间
数据实时性
适用场景
普通视图
2.5秒
2.3秒
0MB
实时
数据量小,实时性要求高
物化视图(表)
0.05秒
0.02秒
50MB
定时更新
数据量大,可接受延迟
缓存表
0.01秒
0.01秒
50MB
手动更新
静态报表,更新频率低
实际测试数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-- 测试查询:SELECT * FROM user_daily_stats WHERE date >= '2024-01-01';
-- 创建员工基本信息视图,隐藏敏感信息如薪资 CREATEVIEW employee_public_info AS SELECT emp_id, -- 员工ID first_name, -- 名字 last_name, -- 姓氏 department, -- 部门 position, -- 职位 hire_date, -- 入职日期 email, -- 邮箱 phone -- 电话 FROM employees -- 从员工表中选择 WHERE status ='active'; -- 只显示在职员工
-- 为不同角色创建不同的视图 -- HR视图:包含薪资信息,只有HR部门可以访问 CREATEVIEW employee_hr_view AS SELECT emp_id, CONCAT(first_name, ' ', last_name) AS full_name, -- 拼接全名 department, position, hire_date, salary, -- 薪资信息,敏感数据 bonus, -- 奖金信息 performance_rating -- 绩效评级 FROM employees WHERE status ='active';
-- 部门经理视图:只能看到本部门员工信息 CREATEVIEW dept_manager_view AS SELECT emp_id, first_name, last_name, position, hire_date, email, phone FROM employees WHERE department =USER() -- 使用当前用户作为部门过滤条件 AND status ='active';
-- 创建实时统计视图,用于仪表板展示 CREATEVIEW dashboard_stats AS SELECT -- 用户统计 (SELECTCOUNT(*) FROM users WHERE status ='active') AS active_users, (SELECTCOUNT(*) FROM users WHEREDATE(create_time) = CURDATE()) AS new_users_today, -- 订单统计 (SELECTCOUNT(*) FROM orders WHERE order_status ='pending') AS pending_orders, (SELECTCOUNT(*) FROM orders WHEREDATE(order_date) = CURDATE()) AS orders_today, (SELECTSUM(total_amount) FROM orders WHEREDATE(order_date) = CURDATE()) AS revenue_today, -- 产品统计 (SELECTCOUNT(*) FROM products WHERE status ='active') AS active_products, (SELECTCOUNT(DISTINCT category_id) FROM products) AS product_categories, -- 系统统计 (SELECTCOUNT(*) FROM system_logs WHEREDATE(created_at) = CURDATE()) AS system_activities_today, NOW() AS last_updated -- 最后更新时间 ;
-- 月度销售趋势视图 CREATEVIEW monthly_sales_trend AS SELECT DATE_FORMAT(order_date, '%Y-%m') ASmonth, -- 月份 COUNT(*) AS order_count, -- 订单数量 COUNT(DISTINCT user_id) AS unique_customers, -- 独立客户数 SUM(total_amount) AS total_revenue, -- 总收入 AVG(total_amount) AS avg_order_value, -- 平均订单价值 SUM(quantity) AS total_items_sold -- 总销售数量 FROM orders WHERE order_status IN ('paid', 'shipped', 'delivered') -- 只统计有效订单 AND order_date >= DATE_SUB(CURDATE(), INTERVAL12MONTH) -- 最近12个月 GROUPBY DATE_FORMAT(order_date, '%Y-%m') -- 按月分组 ORDERBYmonthDESC; -- 按月份降序
-- 为经常查询的列创建索引 -- 单列索引:适用于单一条件查询 CREATE INDEX idx_users_email ON users(email); -- 邮箱索引,用于登录查询 CREATE INDEX idx_users_status ON users(status); -- 状态索引,用于筛选活跃用户
-- 复合索引:适用于多条件查询,注意列的顺序 CREATE INDEX idx_orders_user_date ON orders(user_id, order_date); -- 用户+日期复合索引 CREATE INDEX idx_orders_status_date ON orders(order_status, order_date); -- 状态+日期复合索引
-- 覆盖索引:索引包含查询所需的所有列,避免回表查询 CREATE INDEX idx_orders_cover ON orders(user_id, order_date, total_amount, order_status);
-- 避免在视图中使用复杂的子查询和函数 -- 不推荐:复杂的子查询视图 CREATEVIEW complex_user_stats_bad AS SELECT u.id, u.username, (SELECTCOUNT(*) FROM orders WHERE user_id = u.id) AS order_count, -- 相关子查询,性能差 (SELECTAVG(total_amount) FROM orders WHERE user_id = u.id) AS avg_order, (SELECTMAX(order_date) FROM orders WHERE user_id = u.id) AS last_order_date FROM users u;
-- 推荐:使用JOIN优化的视图 CREATEVIEW user_stats_optimized AS SELECT u.id, u.username, COALESCE(o.order_count, 0) AS order_count, -- 使用COALESCE处理NULL值 COALESCE(o.avg_order, 0) AS avg_order, o.last_order_date FROM users u LEFTJOIN ( -- 使用LEFT JOIN代替子查询 SELECT user_id, COUNT(*) AS order_count, AVG(total_amount) AS avg_order, MAX(order_date) AS last_order_date FROM orders GROUPBY user_id ) o ON u.id = o.user_id;
-- 为视图的基表创建适当的索引 CREATE INDEX idx_orders_user_stats ON orders(user_id, total_amount, order_date);
视图优化前后性能对比:
测试视图:user_stats_optimized(基于100万用户,500万订单)
优化阶段
查询时间
内存使用
CPU使用率
临时表大小
优化措施
原始复杂视图
15.6秒
2GB
95%
800MB
使用相关子查询
JOIN优化后
3.2秒
500MB
60%
200MB
改用LEFT JOIN
添加索引后
0.8秒
150MB
25%
50MB
创建复合索引
最终优化版
0.3秒
80MB
15%
20MB
限制结果集+索引覆盖
具体优化效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-- 优化前的查询执行计划(使用子查询) +----+--------------------+--------+------+---------------+------+---------+------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+--------+------+---------------+------+---------+------+---------+-------------+ | 1 | PRIMARY | u | ALL | NULL | NULL | NULL | NULL | 1000000 | Using where | | 2 | DEPENDENT SUBQUERY | orders | ALL | NULL | NULL | NULL | NULL | 5000000 | Using where | | 3 | DEPENDENT SUBQUERY | orders | ALL | NULL | NULL | NULL | NULL | 5000000 | Using where | +----+--------------------+--------+------+---------------+------+---------+------+---------+-------------+
-- 优化后的查询执行计划(使用JOIN+索引) +----+-------------+--------+------+------------------+------------------+---------+-------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+------------------+------------------+---------+-------+------+-------------+ | 1 | SIMPLE | u | ALL | PRIMARY | NULL | NULL | NULL | 1000000 | Using temporary; Using filesort | | 1 | SIMPLE | o | ref | idx_user_stats | idx_user_stats | 4 | u.id | 5 | NULL | +----+-------------+--------+------+------------------+------------------+---------+-------+------+-------------+
-- 将复杂视图拆分为多个简单视图 -- 第一层:基础数据视图 CREATEVIEW order_basics AS SELECT order_id, user_id, product_id, total_amount, order_date, order_status FROM orders WHERE order_status IN ('paid', 'shipped', 'delivered'); -- 只包含有效订单
-- 第二层:聚合统计视图 CREATEVIEW user_order_summary AS SELECT user_id, COUNT(*) AS total_orders, -- 总订单数 SUM(total_amount) AS total_spent, -- 总消费 AVG(total_amount) AS avg_order_value, -- 平均订单价值 MIN(order_date) AS first_order_date, -- 首次购买日期 MAX(order_date) AS last_order_date -- 最近购买日期 FROM order_basics -- 基于第一层视图 GROUPBY user_id;
-- 第三层:业务逻辑视图 CREATEVIEW customer_segments AS SELECT user_id, total_orders, total_spent, CASE WHEN total_spent >=5000THEN'VIP客户' WHEN total_spent >=2000THEN'重要客户' WHEN total_spent >=500THEN'普通客户' ELSE'新客户' ENDAS customer_segment, DATEDIFF(CURDATE(), last_order_date) AS days_since_last_order -- 距离最后购买天数 FROM user_order_summary; -- 基于第二层视图