由来

知乎上的一个问题:Django 分表 怎么实现?

这个问题戳到了Django ORM的痛点,对于多数据库/分库的问题,Django提供了很好的支持,通过using和db router可以很好的完成多数据库的操作。但是说到分表的问题,就有点不那么友好了。但也不是那么难处理,只是处理起来不太优雅。

解析

在Django中,数据库访问的逻辑基本上是在Queryset中完成的,一个查询请求,比如:User.objects.filter(group_id=10)。

其中的objects其实就是models.Manager,而Manager又是对QuerySet的一个包装。而QuerySet又是最终要转换为sql的一个中间层(就是ORM种,把Model操作转换为SQL语句的部分)。所以当我们写下User.objects的时候,就已经确定了要访问的是哪个表了,这是由class Meta中的db_table决定的。

class 

理论上讲,我们可以通过在运行时修改db_table来完成分表CRUD的逻辑,但是the5fire在看了又看源码之后,还是没找到如何下手。还是上面的问题,当执行到User.objects的时候,表已经确定了,当执行到User.objects.filter(group=10)的时候只不过是在已经生成好的sql语句中增加了一个where部分语句。所以并没有办法在执行filter的时候来动态设置db_table。

对于问题中说的get也是一样,因为get本身就是在执行完filter之后从_result_cache列表中获取的数据(_result_cache[0])。

方案一

根据the5fire上面的分析,要想在执行具体查询时修改db_table已经是不可能了(当然,如果你打算去重写Model中Meta部分的逻辑以及Queryset部分的逻辑,就当我没说,我只能表示佩服)。

所以只能从定义层面下手了。也就是我需要定义多个Model,同样的字段,不同的db_table。大概是这样。

class 

这样在User.objects.get(id=3)的时候,如果按照模2计算,那就是User01.objects.get(id=3),笨点的方法就是写一个dict:

user_sharding_map 

如果真的这么写那Python作为动态语言,还有啥用,你分128张表试试。我们应该动态创建出User01,User02,....UserN这样的表。

class 

嗯,这样看起来似乎好了一下,但是还有问题,id=3需要传两次,如果两次不一致,那就麻烦了。Model层要为上层提供统一的入口才行。

class MyUser(models.Model):# 增加方法 BY the5fire@classmethoddef sharding_get(cls, id=None, **kwargs):assert id, 'id is required!'Model = cls.get_sharding_model(id=id)return Model.objects.get(id=id, **kwargs)

对上层来书,只需要执行MyUser.sharding_get(id=10)即可。不过这改变了之前的调用习惯 objects.get 。

不管怎么说吧,这也是个方案,更完美的方法就不继续探究了,在Django的ORM中钻来钻去寻找可以hook的点实在憋屈。

我们来看方案二吧

方案二

ORM的过程是这样的,Model——> SQL ——> Model,在方案一中我们一直在处理Model——> SQL的部分。其实我们可以抛开这一步,直接使用raw sql。

QuerySet提供了raw这样的接口,用来让你忽略第一层转换,但是有可以使用从SQL到Model的转换。只针对SELECT的案例:

class 

大概这么个意思吧,代码可以再严谨些。

总结

单纯看方案一的话,可能会觉得这么大量数据的项目,就别用Django了。其实the5fire第一次尝试找一个优雅的方式hack db_table时,也是一头灰。但是,所有的项目都是由小到大的,随着数据/业务的变大,技术人员应该也会更加了解Django,等到一定阶段之后,可能发现,用其他更灵活的框架,跟直接定制Django成本差不多。

补充两个github repo: - JBKahn/django-sharding - disqus/sharding-example

----EOF-----

扫码关注,或者搜索微信公众号:Python程序员杂谈

django model filter_Django分表的两个方案相关推荐

  1. django全自动分库分表(横向)

    django全自动分库分表 期待大神指点方法的不足之处或者其他更好的方法 由于当前项目目前只需要实现写,所以这里也没有考虑读写分离.如果要考虑读写分离,则在路由处进行设置即可. 分库原理 django ...

  2. 架构组件:基于Shard-Jdbc分库分表,数据库扩容方案

    架构组件:基于Shard-Jdbc分库分表,数据库扩容方案 一.数据库扩容 1.业务场景 互联网项目中有很多"数据量大,业务复杂度高,需要分库分表"的业务场景. 这样分层的架构 ( ...

  3. django model filter_Django开发常用方法及面试题

    Django开发常用方法及面试题 目录 1. 对Django的认识? 2. Django .Flask.Tornado的对比 3. 什么是wsgi,uwsgi,uWSGI? 4. django请求的生 ...

  4. 秋色园QBlog技术原理解析:性能优化篇:数据库文章表分表及分库减压方案(十五)...

    文章回顾: 1: 秋色园QBlog技术原理解析:开篇:整体认识(一) --介绍整体文件夹和文件的作用 2: 秋色园QBlog技术原理解析:认识整站处理流程(二) --介绍秋色园业务处理流程 3: 秋色 ...

  5. MySQL 分库分表及其平滑扩容方案

    作者:王克锋 出处:https://kefeng.wang/2018/07/22/mysql-sharding/ 众所周知,数据库很容易成为应用系统的瓶颈.单机数据库的资源和处理能力有限,在高并发的分 ...

  6. 数据库调优过程(五):物理分表,及写入方案调整

    背景: enb下包含多个文件,我们需要解析这样的数据到数据库中,供应用端计算分析使用.之前,我们已经采用了分表方案,分表分为一个主表,三个子表.每一个enb一套表. 解析业务: 每取到一个文件就读取为 ...

  7. MySQL关于分库分表及其平滑扩容方案

    众所周知,数据库很容易成为应用系统的瓶颈.单机数据库的资源和处理能力有限,在高并发的分布式系统中,可采用分库分表突破单机局限.本文总结了分库分表的相关概念.全局ID的生成策略.分片策略.平滑扩容方案. ...

  8. 分库分表技术及技术方案

    一.分库分表的必要性 分库分表技术的使用,主要是数据库产生了瓶颈,如单库的并发访问或单表的查询都超出了阈值.对系统使用造成一定的影响,不得已而产生的技术. 通过分库分表技术来解决此类问题,但正因为使用 ...

  9. postgresql分库分表中间件开源实现方案

    PostgreSQL 分库分表的中间件开源实现方案有很多, 你可以根据自己的需要选择适合自己的方案. 下面是几种常见的方案: pgpool-II: 一个 PostgreSQL 透明数据库代理, 具有负 ...

最新文章

  1. socket编程报异常java.io.EOFException
  2. python比较好的书籍推荐-推荐几本2019年初学者学习Python最佳书籍!
  3. php和python区别-PHP与Python语言有哪些区别之处?选择哪一个好?
  4. 第12章:项目采购管理(2)-章节重点
  5. OPPO尝鲜android版本更新,安卓11迎来四大贴心升级,OPPO小米率先尝鲜
  6. OpenCV gapi模块OMZ文本检测的实例(附完整代码)
  7. Python之——遇到的小知识点总结
  8. IPython快捷键及命令
  9. C#开发笔记之11-如何用C#过滤连续相同的字符串?
  10. 非局部均值(Nonlocal-Mean)
  11. FineReport:任意时刻只允许在一个客户端登陆账号的插件
  12. 【李宏毅机器学习】Logistic Regression 逻辑回归(p11) 学习笔记
  13. php7 viewmodel,ViewModel浅析
  14. SQLServer导数据到Oracle
  15. nginx+lua搭建文件上传下载服务
  16. VS2010-MFC(Ribbon界面开发:为Ribbon Bar添加控件)
  17. Java Access Bridge
  18. 杭电acm--2154跳舞毯
  19. quartz 每月一次_quartz cron表达式 每周一0点怎么设置
  20. Anmle,Factors,andMultiFactorModels

热门文章

  1. jquery判断多选框是否选中
  2. 三个斯坦福华裔学生,送外卖成亿万富翁
  3. 写给初学者的Tensorflow介绍
  4. vector使用排序函数实例
  5. base64的c语言实现方法
  6. java百度云推送demo_百度云推送java服务端maven安装完整demo
  7. 文件内容查找java,java库从文件内容中查找mime类型
  8. 约瑟夫环java链表_java使用链表实现约瑟夫环
  9. excel字符串和单元格拼接_Excel实例分享-学会输入数据小技巧,让你的工作效率远超同事...
  10. 服务中没有listen_Go语言微服务框架实战:2.Go语言实现RPC编程绍