博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django的数据模型层实现特点
阅读量:5321 次
发布时间:2019-06-14

本文共 2175 字,大约阅读时间需要 7 分钟。

我在数据层的抽象上走了一段比较长的弯路。简单总结一下:

刚开始做简单的项目时,用简单的ActiveRecord就已经很合适了,比如CodeIgniter自带的。但是项目变大之后,特别是业务实体之间的关联变多之后马上就出现了问题,为了降低各个实体间的耦合,你需要将各种操作再抽象出一层。举个例子:你做了一个简单的用户系统,对用户的增删改查只需要对“用户类”调用相应的操作就行了。后来你增加了一个文件类,每个用户可以拥有多个文件,删除用户时需要同时删除相应的文件。为了能使删除的用户的这个操作复用,同时防止其他操作删除用户时没有删除相应文件夹,于是你不得不再对用户的删除做一层封装。我曾经试图让各种实体在构建的时候就说明与其他实体的关系,这样写业务逻辑的时候就能尽量少的受打扰。后来发现这也是错误的,因为把关系写到数据层以后,遇到特殊的逻辑就很难操作了。还是刚才那个例子:如果有一天我增加了一个分享功能,同时规定删除用户时不删除他已经分享的文件,这时该怎么办?当然有些其他绕的方法可以实现,比如分享文件的时候就复制文件到另一个特殊的用户账户下,用户读取的分享文件其实都是这个特殊用户账户的。但是系统大了之后,这种特殊方法就会多得烦人。后来在我写climbPHP时,才算是找到了一个较为合理的方法。就是系统应该以具体的业务逻辑来分模块,数据实体是从属于业务逻辑模块的。模块间的联系是通过抛出和监听事件实现的。数据实体之间不再有直接的关联。还是以刚才的背景来举例子:系统分为用户、文件、分享三个模块,用户模块接受正常的删除指令,成功后向外抛出事件。文件模块监听用户删除事件,同时删除相应的文件。分享模块也监听用户删除事件,监听到之后获取用户除了分享出去的文件以外可删除的文件,然后阻断原来的用户删除事件,改为抛出可删除文件的事件。这样的好处在于,每一个模块开发完成之后都可以完全封闭。当系统关闭共享模块时,原有系统不需要任何改动,仍然可用。不过这样做的前提在于需要有一个足够强大的事件派发中心。参见。

对ORM我没有用到过真正的项目中,一是因为有些业务逻辑太复杂,调研的ORM都不能满足性能上的需求。二是因为语法太难看,不想用。学Django的时候发现Django的数据模型层很成熟,具体特点记录如下:

1.对关联实体查询的优化。

这一部分应该是最影响数据库性能的。Django在查询有关联实体的实体时,默认时先查询主实体,然后根据关联项依次查询对关联实体。如果你查询的主实体是多个,那么会依次对每一个再去数据库查询相关联的实体。为了优化,Django提供了一个prefetch_related方法,能一次性查询所有相关联的实体,然后通过python组装。对于一对一的关联,Django还提供了selecte_related方法,这个方法使用的join来查询。

除了在查询方法上加速,Django还支持“关联对象”的延迟加载,也就是当访问关联的对象时才再次访问数据库。这一点我特别注意了一下,因为最近读了CSDN范凯的关于ORM的总结,他说实际项目中数据库的瓶颈在于IO而不是并发。将复杂的查询拆分成简单的数据库查询可以极大地提高缓存利用率,降低磁盘IO。但是Django延迟载入关联实体在实际情况下性能如何我没有考证过。

这里值得注意的是,Django在实现数据模型层的时候应该是用到了python语言本身扩展自己语法的特性。因为它直接使用了python的切片语法来实现sql的limit操作。如 users.objects.all()[0:5],在Django文档中说明了all()操作会造成数据库访问,如果没有对语法进行扩展的话,那么切片时岂不是已经对数据库进行了全表查询?

2.对查询结果的数据缓存。

对普通的数据查询来说,Djang没有提供特别的缓存方式,需要用户手工用变量来缓存上次查询的结果。对于关联数据,如果执行了select_related()或者prefetch_related(),那么通过self来读取关联实体时读取的是缓存。

3.模型的继承。

Django提供了三种继承方式,php的Doctrine也实现了类似的方式。三种继承分别是:“继承自抽象父类”,“继承自普通数据模型”,“继承变成代理”。具体意义分别是:“抽象父类只包括通用属性或者方法,本身不能生成表”;“继承后的模型对自己的特有字段生成新表”;“继承后的模型不生成新表,只是一个可以复写源模型行为的代理”。

 

总结:

1.关于ORM感觉已经没有太多值得讨论的了,请看CSDN范凯的 《WEB的缓存设计模式》。

2.数据层以及持久化的具体实现其实不需要纠结,目前的ORM已经足够强大,真正纠结的是业务逻辑造成的数据模型关联。也是我开篇一堆废话所说的。

3.Django数据模型层对python本身特性的使用让我很感兴趣,这在php中是没有的。下一篇准备研究python扩展自身的能力。

4.NOSQL将如何改变框架中的数据模型层?我认为没有太大改变,如上所说,数据库如何变化说到底只是数据如何持久化。框架始终关注的是如何更好的表现业务逻辑。

转载于:https://www.cnblogs.com/sskyy/archive/2013/03/12/2955929.html

你可能感兴趣的文章
2018.11.06 bzoj1040: [ZJOI2008]骑士(树形dp)
查看>>
2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
查看>>
redis cluster 集群资料
查看>>
微软职位内部推荐-Sr. SE - Office incubation
查看>>
微软职位内部推荐-SOFTWARE ENGINEER II
查看>>
centos系统python2.7更新到3.5
查看>>
C#类与结构体究竟谁快——各种函数调用模式速度评测
查看>>
我到底要选择一种什么样的生活方式,度过这一辈子呢:人生自由与职业发展方向(下)...
查看>>
poj 题目分类
查看>>
windows 安装yaml支持和pytest支持等
查看>>
读书笔记:季羡林关于如何做研究学问的心得
查看>>
面向对象的优点
查看>>
套接口和I/O通信
查看>>
阿里巴巴面试之利用两个int值实现读写锁
查看>>
浅谈性能测试
查看>>
Winform 菜单和工具栏控件
查看>>
jequery动态创建form
查看>>
CDH版本大数据集群下搭建的Hue详细启动步骤(图文详解)
查看>>
第六次java作业
查看>>
巧用Win+R
查看>>