使用数据图视图的起因
最近在做一个销售数据统计的功能,把数据表中的实时产生的销售数据按天做统计计算。于是在MySQL数据库中做了一个视图,很容易得到每天的统计数据,并且有新的数据产生时,能实时查看到当天的数据更新。
视图的数据是建立在数据表基础上的,把统计的SQL调试好之后,生成数据库视图,后续的查询可以直接数据库视图来完成,这样在Django中编写查询的代码就简单多了,不需要做统计计算。
Django访问数据库视图
参照网上找的资料,Django访问数据库视图的参考代码如下,重点是class Meta信息中要设置 managed = False。表格的字段申明要与视图的字段一一对应,另外主键字段和排序字段的申明,似乎不能起到作用。
# 备份表格,用于数据同步 class BranchDailyAchievementBackup(models.Model): branchid = models.IntegerField(primary_key=True) fullname = models.CharField(max_length=_LEN_FULLNAME, verbose_name='名称') cdate = models.DateField() sumtotal = models.FloatField() class Meta: managed = False ordering = ["cdate", "branchid"] db_table = "branchdailyachv_backup"
到这里已经可以用这个Model 来查询数据库视图的数据了。
问题来了:
实际测试时,发现这里的查询操作实际上非常慢,可能是每次查询,都在数据库中重新执行一次视图的SQL语句。但是如果把数据库视图转变成数据表之后,这些数据已经存在表格中了,查询起来就快多了。
对于数据库中已有的表格数据访问方式,和数据库视图的访问方式一样,可以按上面的方法定义Model。
把数据从视图转存到表格的SQL语句如下:
CREATE TABLE branchdailyachv_backup AS SELECT * FROM branchdailyachv_view;
这样又带来一个问题:视图中的数据转存到表格后,数据已经固化了,不会因为新的数据产生而动态更新了。
结合现在统计数据的特点,只需要更新当天的数据就可以了,之前的数据不会发生变化。
于是有了新的思路:
先用根据视图生成一个数据表格1,然后定时的生成数据表2,然后把表2中最新的数据更新到表1。这样表1是一直存在并且定时更新的,表2会不断的重新生成,每次生成之前需要删除数据表,但是用户的查询操作是针对表1的,所以表2的删除操作对用户查询不影响。
然后按照这个思路写代码,做好之后又出现了新的问题:
在更新这个表1的数据时,执行save()操作之后,数据库中会出现很多条重复的记录。具体的原因不清楚,但应该是因为设置了 managed = False的原因。
重新整理思路:
- 创建数据库视图
- 根据数据库视图生成数据表格2.
- 在Django中生编写表格模型1, managed = True 。
- 编写访问数据库视图的模型2,设置 managed = False,并且让表格1和表格2的内容一致。
- 定时将表格2的数据更新到表格1。 首次更新操作时,表格1的内容为空,需要将表格2的全部数据更新到表格1。这样Django就能正常地查询表格1的数据了,并且因为用户不会查询表格2,所以表格2删除后重建也不会有影响。