django项目到底要不要使用外键?
这个问题对于开发的老油条来说,肯定是心照不宣了,基本上都是say no。
但是在客观来看,这个问题不能够一概而论,都是需要基于现实情况来看。
对于新手来说,在没有太多经验的情况下,会很不理解,为什么哪些老油条都说不要使用外键,但是却没有给他们说明原因,只是摆出一副 ‘这你都不懂’ 的鄙视的脸色。好吧,其实我也遇到过,而且后来我也摆过类似的脸色,真是冤冤相报何时了。
所以在这里我就分享一下我自己本身的一个切身的经历,也算是一个总结吧。
从我自己本身经历的一个项目来讲吧。公司在开发产品的流程中,因为bug的管理非常乱,现有的工具不是非常合适我们使用,然后我的上司就给我布置了一个项目,1个星期之内做一个bug的管理工具出来。好吧,既然这样,问了一下需求,就直接开干,基于django来开发。当然,时间这么紧,由不得我多想,django的orm这么爽,当然要物尽其用,自然就用了很多外键。一个星期后,产品正式上线,然后风风火火地使用了。产品嘛,你也知道,用着用着,就肯定会有更多的需求和优化。那就继续干呗,继续加需求,然后继续开干了。就这样过了很长一段时间,后面用的人越来越多了,数据量也越来越多了,接口的响应速度越来越慢。同时伴随着需求的增多,需求肯定赶不过来,那怎么办,加人呗。当新人来干的时候就出现了问题了,makemigrations不成功,尼玛,怎么回事。查了很多才发现,是外键出现互相引用了,导致没法正确的建表,例如:
有两个app---app1,app2, app1的表1引用app2的表2, app2的表1引用了app1的表2。完了,只能是手动一个一个的创建表,光环境都搞了半天。好几个新人,每个人都这么搞,我靠,烦的要命。
这是其一,另外,发现接口的响应速度越来越慢,一个接口好几秒才返回,调试代码发现,原来是过于依赖orm, orm执行的SQL语句太多了,而且存在多个外键,更加是雪上加霜,sql语句数量加多了好几倍。例如:
表table1 存在 5个a b c d e外键, 那么在使用orm访问表1的对象的时候,不仅仅执行了表1的查询语句:
select * from table1 where id=id
select * from a where id=id
select * from b where id=id
select * from c where id=id
select * from c where id=id
select * from d where id=id
一旦去循环访问每一个 table1 的各个对象,简直是灾难,执行的sql语句数量庞大。
这里说到了另外一个问题了,就是orm的问题所在,orm虽然方便,但是无形中执行的sql语句可能是灾难级别的。
对于上面两个问题,已经是非常严重,那么如何优化这个,只能是干掉所有的外键,减少sql语句的数量。最终,项目里面所有的外键都干掉了。
对于外键来说,有好处,也有坏处,在这里在这里总结几点。
django项目使用外键的好处:
1. 非常方便,结合django 的orm能够实现非常复杂的查询方式,orm的跨表查询必须要结合外键才能够发挥它的最大的效果。特别是manyField这种多对多的方法,方便到极致,刷新了我的世界观;最重要的是开发效率非常高,对于小项目来说是非常合适的。
2. 代码非常工整,摈弃了在代码里面写各种不和谐的sql语句。
想想代码里面没有一句sql语句,真爽。
3. 不同数据库的可移植性比较好,不同的数据库可以用同一套代码。
基本是可以随时更换数据库,例如sqllite, mysql,无缝切换,只要改变一下配置就可以了
4. 保持了数据的完整性,不会出现脏数据。
简单来说,多个表如果存在外键关联,那么这几个表就是一个整体,不会出现某个表的数据缺失的情况。
django项目使用外键的坏处:
1. 就像上面所说的第一点,一旦出现互相引用的情况,建表都会有问题了,当然,实际上这个是我本身设计表不合理导致了,但是也说明,外键无形中添加了很限制。
2. 在使用orm的时候,如果存在外键,有可能会导致sql语句成倍的增长,限制了效率。不限制外键能够减少sql语句的数量
3. 使用外键,sql语句执行效率会很慢。
不用外键时数据管理简单,操作方便,性能高:
导入导出等操作,在insert,update,delete数据的时候速度是非常快的,如果使用了外键,insert,update,delete 每次都会去检查关联表,增加了很大的开销,在海量的数据库中想都不要去想外键,试想,一个程序每天要insert数百万条记录,当存在外键约束的时候,每次要去扫描此记录是否合格,一般还不止一个字段有外键,这样扫描的数量是成级数的增长!
4. 数据表之间存在关联,在代码设计的属于来说,耦合性太强,不利于系统的拓展。
这个比较专业,就是一个系统的数据耦合性太强,你没做一个修改,都要考虑是否会影响整个系统,真正其一发而动全身,效率比较低,容易出问题。但是如果没有外键,那么就我干我的,不会影响你的,对于多人一起开发的系统来说,效率就很高了,也不容易出问题。
结论:
1. 在小型项目的时候,外键真的物尽其用,随便用,而且是最好使用外键,看看我的项目在初期的时候,非一般的速度
2. 在大型系统中, 有性能要求高,一般不用外键,就像我的项目一样,一旦做大,就废弃了外键的使用;
这里就引出了如何在django里面使用orm性能最好的问题,这里就不讨论,下一篇文章里面分享