本文正在参加「技术专题19期 漫谈数据库技术」活动
视图是sql当中的一个很重要的知识点,本身难度并不高,但是,什么时候使用,一直让人很困惑,因为视图其实会影响到查询的效率,那么我们通过用户,商品和订单来聊聊MySQL的视图的使用场景。
场景
一个电商平台,每天要有很多笔交易,离不开两个个业务主体,就是商品,订单。除了常规的业务查询之外,电商平台都会基于运营需求去统计商品的销售情况,为店铺的成长或者平台规划提供依据,我们以订单表为核心来聊一聊视图,首先看一下表结构:
(当然,这里只是为了展示视图功能,表结构做了简化)
mysql> desc goods;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| goods_name | varchar(32) | YES | | NULL | | #商品名称
| count | int(11) | YES | | NULL | | #商品数量
| goods_price | float | YES | | NULL | | #商品价格
| origin_place | varchar(200) | YES | | NULL | | #生产场地
| origin_time | varchar(20) | YES | | NULL | | #生产日期
+--------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> desc order_info;
+------------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| consignee | varchar(32) | YES | | NULL | | #收货人
| consignee_phone | varchar(14) | YES | | NULL | | #收货人电话
| total_amount | float | YES | | NULL | | #订单总价格
| order_status | int(11) | YES | | NULL | | #订单状态
| user_id | int(11) | YES | | NULL | | #用户id
| goods_id | int(11) | YES | | NULL | | #商品id
| store_id | int(11) | YES | | NULL | | #店铺id
| payment_way | int(11) | YES | | NULL | | #支付方式
| delivery_address | text | YES | | NULL | | #送货地址
| order_comment | text | YES | | NULL | | #订单备注
| create_time | varchar(20) | YES | | NULL | | #创建时间
| parent_order_id | int(11) | YES | | NULL | | #父订单编号
| feight_fee | float | YES | | NULL | | #运费
+------------------+-------------+------+-----+---------+----------------+
12 rows in set (0.00 sec)
上面是表结构,下面来看一下业务需求吧,每个月生产一封关于平台的订单报表:
包括订单量最高的三种商品,
每天订单的数量
每天订单创建的时间分布
等等
视图
结合上面的需求来聊聊视图:
1、视图是虚表,没有行,也没有列,更没有数据,只是通过一个查询语句构建的虚拟的表结构,具有和真实表类似的功能,但是每次使用视图,都会执行构建虚表的查询语句,所以查询的速度比较慢,我们查询一个商品的订单量,首先是一个复杂的嵌套查询,本身编写起来比较复杂,而且每个月查询一次,对查询效率的要求也不高,那么在这种场景下,使用视图先构建出来一个契合业务的表,然后基于这个表查询会方便很多。
2、视图本身是基于其他表的查询,所以可以用视图作为隔离,返回一张过滤后的表,这样对数据安全也是有好处的,订单表本身含有的信息比较多,在上面的这个需求当中实际上使用到的订单表的字段并不多,或者说只是数量统计,那么这个时候采用视图表,访问视图表会和原来的订单表和商品表形成隔离,也有了一定的安全意义。
3、在业务层面数据展示的过程当中,比如对时间的格式等字段都是有特殊要求的,如果直接查询,那么到了服务端或者前端渲染不得不从新循环数据,对数据的格式进行修改,但是使用视图就可以在构建表的时候,调整数据格式来配合业务需求,方便服务的和前端的使用。
4、还有一个点,基于sql语句的编写,视图更像是编程过程当中的函数,提高了代码的复用程度,便于sql语句的维护。
所以可以构建这样的一个视图来复用嵌套查询:
create view goods_order as
select
goods_name,
(select count(*) from order_info where order_info.goods_id = goods.id) as order_number
from goods order by order_number desc limit 5;
mysql> select * from goods_order;
+------------+--------------+
| goods_name | order_number |
+------------+--------------+
| 超级奶茶1 | 999 |
| 超级奶茶2 | 888 |
| 超级奶茶3 | 777 |
| 超级奶茶4 | 666 |
| 超级奶茶5 | 555 |
+------------+--------------+
1 row in set (0.00 sec)
或者这样修改查询的结构格式
create view goods_comment as
select concat(goods.goods_name,"(",order_info.order_comment,")") as goods_comment from goods,order_info where order_info.goods_id = goods.id;
mysql> select * from goods_comment;
+----------------------+
| goods_comment |
+----------------------+
| 超级奶茶(加糖不加冰) |
| 超级奶茶(加冰不加糖) |
+----------------------+
2 rows in set (0.01 sec)
所以基于上面再看视图,是不是有所了解了,今天就先聊这么多,还请大家多多指点呀。
本文正在参加「技术专题19期 漫谈数据库技术」活动