数据库查询优化

orm语句的特点:惰性查询

如果仅仅只是书写了orm语句,在后面没有用到该语句所查询出来的参数,那么orm会自动识别,并不执行

举例:

res = models.Book.objects.all()
# 单单执行此语句Django并不会使用数据库,减轻数据库压力
res = models.Book.objects.all()
print(res)
# 只有用到数据了才会走数据库

接下来尝试获取数据表中所有书的名字。

res = models.Book.objects.values('name')
print(res)  # 拿到列表套字典的形式,对象
for i in res:print(i.get('name')) # 通过for循环字典取值方式拿到书籍名字

那么如何实现获取到的是一个数据对象,再通过title就能够拿到书名,并且没有其他字段。

only与defer

only

res1 = models.Book.objects.only('name') # 对象只有name属性
for b in res1:print(b.name) # 如果(.)only括号内有的字段则不走数据库print(b.title) # 如果(.)only括号内没有的字段则需要反复前往数据库查询数据,再一个一个返回,而all()不需要

结论:因为all()拿到的是所有的数据对象,而only()只拿到括号内指定的数据对象。

defer

res = models.Book.objects.defer('name')  # 对象除了没有name属性之外其他的都有
for i in res:print(i.price)

结论:defer与only刚好相反,defer括号内放的字段不再查询出来的对象中,查询该字段需要重新走数据库。如果查询的是非括号内的字段,则不走数据库。

select_related与prefetch_related:与跨表操作有关

select_related

举例:查询每本书的的出版社名字

res = models.Book;.objects.all()
for i in res:print(i.publish.name)
# 使用all方法查询的时候,每一个对象都会去数据库查询数据

res = models.Book.objects.select_related()
for i in res:print(i.publish.name) # 只走了一次数据库, 使用INNER JOIN内连接操作

总结:select_related 内部直接先将book与publish连接,然后一次性将大表里面的所有数据全部封装给查询出来的对象。select_related括号内只能放外键字段并且是一对多,一对一。

prefetch_related

# 跟跨表操作有关res = models.Book.objects.prefetch_related('publish')  # 子查询
for i in res:print(i.publish.name)"""prefetch_related该方法内部其实就是子查询将子查询查询出来的所有结果也给你封装到对象中给你的感觉好像也是一次性搞定的
"""

结论:prefetch_related该方法内部其实就是子查询,将子查询出来的所有结果封装到对象中。

总结:select_related与prefetch_related,select_related是连表操作,prefetch_related是子查询,各有优点与缺点,如果表很大的时候,使用select_related连表耗时会耗费很长时间,而select_related子查询虽然查询两次,但是操作两个表的时间非常短效率就会胜于联表查询prefetch_related

choices参数(数据库字段设计常见)

针对信息来源可概括全部场景。比如:性别,学历,工作经验,信息来源... 这种情况该如何存储?

只要是某个字段的可能性是可以列举完全的,一般情况下都会采用choices参数

字段创建的数据类型根据想要指定字段中一个元祖元素是什么类型。该gender字段存的还是数字,但是如果存的数字在上面元祖列举的范围之内,那么可以获取到数字对应的真正的内容。

举例:

# 如果gender字段存的数字不再上述元祖列举的范围内容
# 如果在,如何获取对应的中文信息?

创建表:

class Client(models.Model):username = models.CharField(max_length=32)age = models.IntegerField()# 性别gender_choices = {(1, '男'),(2, '女'),(3, '其他'),}"""字段创建的数据类型根据想要指定字段中一个元祖元素是什么类型。该gender字段存的还是数字,但是如果存的数字在上面元祖列举的范围之内那么可以获取到数字对应的真正的内容"""gender = models.IntegerField(choices=gender_choices)

创建数据,tests.py:

from django.test import TestCase# Create your tests here.
import os
import sysif __name__ == "__main__":os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day06.settings")import djangodjango.setup()from app01 import modelsmodels.Client.objects.create(username='junjie',age=18,gender=1)models.Client.objects.create(username='nn',age=1,gender=2)models.Client.objects.create(username='jason',age=58,gender=3)models.Client.objects.create(username='tom',age=99,gender=4)

可以看到,数据的创建是没有问题,没有创建的数字也能存

那么取?

# 取
user_obj = models.Client.objects.filter(pk=1).first()
print(user_obj.gender)
# 输出:1

此时输出不应该是pk=1所对应的真正性别,怎么获取的数据是1?

只要是choices参数的字段,如果想要获取对应信息,固定写法get_字段名_display()

user_obj = models.Client.objects.filter(pk=1).first()
print(user_obj.get_gender_display())
# 输出:男

那么还有一个用户名为tom没有书写固定关系,他返回的会是什么?

user_obj = models.Client.objects.filter(pk=4).first()
print(user_obj.get_gender_display())
# 输出:4

如果没有对应关系,字段是什么还是展示什么。

字符串格式也是如此:

先创建字段:

score_choices = (('A','优秀'),('B','及格'),('C','不及格'),
)
# 在已创建的表中添加新的字段,需要设置null=True 表示该字段为空,也可以设置默认值
score = models.CharField(max_length=32,choices=score_choices,null=True)

添加数据:

models.Client.objects.filter(pk=1).update(score='A')

获取数据:

res = models.Client.objects.filter(pk=1).first()
print(res.get_score_display())
# 输出:优秀

MVC和MTV模型

  • MTV: Django号称是MTV模型,本质也是MVC模型
    M: models
    T: templates
    V: views

  • MVC
    M: models
    V: views
    C: controller(控制器)

多对多三种创建方式

  • 全自动

    • 优点: 代码不需要写,方便,支持orm提供操作第三张关系表的方法...
    • 缺点: 第三张关系表的扩展性极差(没办法添加额外的字段)
  • 纯手动
    • 优点: 第三张表完全取决于自己额外的扩展
    • 缺点: 需要写的代码加多,不能使用orm提供的简单方法,正反向查询之类...
  • 半自动

全自动

利用orm自动创建第三张关系表

class Book(models.Model):name = models.CharField(max_length=32)authors = models.ManyToManyField('Author')class Author(models.Model):name = models.CharField(max_length=32)

纯手动

class Book(models.Model):name = models.CharField(max_length=32)class Author(models.Model):name = models.CharField(max_length=32)class Book2Author(models.Model):authors_id = models.ForeignKey(to='Author')books_id = models.ForeignKey(to='Book')

半自动

through_fields 字段先后顺序,判断的本质: 通过第三张表查询对应的表,需要用到那个字段酒吧哪个字段放前面,当前表是谁,就把对应的关联字放在前面。

半自动:可以使用orm正反向查询,但是没办法使用add,remove,clear,set 方法

class Book(models.Model):name = models.CharField(max_length=32)authors = models.ManyToManyField(to='Author',# 声明指定表为第三张关系表through='Book2Author',# 声明在第三张关系表中的字段表示关系through_fields=('Book','Author'))class Author(models.Model):name = models.CharField(max_length=32)class Book2Author(models.Model):authors = models.ForeignKey(to='Author')books = models.ForeignKey(to='Book')...

总结:全自动和半自动需要掌握,为了拓展性更高一般都采用半自动

Django 数据库查询优化,choices参数(数据库字段设计常见),MVC和MTV模型,多对多三种创建方式...相关推荐

  1. Django09:图书管理系统笔记/choices用法/ MTV与MVC模型/多对多三种创建方式

    图书管理系统笔记 redirect括号内可以直接写url 也可以直接写别名 但如果别名需要参数,必须使用reverse解析. choices用法 使用场景:能列举完全的数据 #使用方法:xxx_cho ...

  2. choices参数(数据库字段设计常见)

    chocies参数使用场景是非常广泛的,直接上代码 """ 用户表 性别学历工作经验是否结婚是否生子客户来源... 针对某个可以列举完全的可能性字段,我们应该如何存储只要 ...

  3. python操作数据库的几种方法_python对mysql数据库操作的三种不同方式

    原标题:python对mysql数据库操作的三种不同方式 |转载自:博客园 |原文链接:http://www.cnblogs.com/mryrs/p/6951008.html 先要说一下,在这个暑期如 ...

  4. PyQt5随笔:Qtdesigner设计转换而来的界面.py文件两种调用方式

    PyQt5随笔:Qtdesigner设计转换而来的界面.py文件两种调用方式 文章目录 PyQt5随笔:Qtdesigner设计转换而来的界面.py文件两种调用方式 1.前言 2.方式一:另建 py ...

  5. 【值传递和引用传递之外的第三种传值方式 - 传名参数】

    引言 先看下Scala 的以下方法该如何调用那? class Demo {val assertIsOpen = truedef test(isTrue: () => Boolean): Unit ...

  6. mysql数据库查询优化建议_mysql数据库查询优化的24条建议

    MySQL是一个强大的开源数据库.随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈.这里提供一些关于Mysql 数据库查询优化的24条优化建议,仅供参考. Mysql 查询优化 1.使用慢查询 ...

  7. 主要用于收集数据库服务器性能参数,数据库-布布扣-bubuko.com

    一系统数据库:  information_schema: 虚拟库, 不占磁盘空间, 存储数据库启动后的一些参数, 如用户表信息, 列信息/权限信息/字符信息等等 performance_schema: ...

  8. 【数据库Redis】Redis五种基本数据结构以及三种配置方式——默认配置、运行配置、配置文件启动

    文章目录 一.初识Redis 1.1 了解Redis 1.2 Redis特性 1.3 Redis使用场景 Redis不适合场景 1.4 用好Redis的建议 1.5 正确安装并启动Redis 在Lin ...

  9. easyui数据表格重置_数据库三种删除方式

    第一种 使用delete 语句 特点: delete 属于数据库操纵语言DML,表示删除表中的数据, 删除过程是每次从表中删除一行,并把该行删除操作作为事务记录在日志中保存 可以配合事件(transa ...

最新文章

  1. 使用 XML 实现 REST 式的 SOA
  2. 【软件开发底层知识修炼】六 Binutils辅助工具之- addr2line与strip工具
  3. ruby 发送post请求_使用Ruby发送电子邮件
  4. java期末项目实验答辩毕业设计工程项目源码
  5. vs可以编译python_Python如何进行编译和反编译
  6. 拥有开源安全背景的开发员当选白宫技术总监
  7. java时区_Java时区
  8. [转]首次新型智慧城市评价工作将侧重应用效果和民众感受
  9. ios plist获取权限
  10. 使用scrapy-redis构建简单的分布式爬虫
  11. MATLAB处理txt文档数据——以处理pscad输出数据为例
  12. HFSS - 倒F天线的设计与仿真
  13. 单核工作法图解:事多到事少,拖延变高效
  14. C语言之二维数组定义、初始化、赋值、求最大最小、求和
  15. Tushare实战分析美国国债收益率与利率的关系
  16. #12304;#28404;#28404;#37329;#59257;#34701;#23458;#59257;#26381;#30005;#35805;#12305;
  17. java 生成格林威治时间
  18. 对路径“C:\Inetpub\wwwroot\UploadFile\AssertTemple1.xls”的访问被拒绝。
  19. python 查tensorflow版本_查看已安装tensorflow版本
  20. android ios mp4格式转换,ios格式转换器|iphone视频格式转换器免费版 7.1 - 系统天堂...

热门文章

  1. c语言关于内存笔试,4、C语言面试笔试--内存操作-指针
  2. c语言安卓录屏,手写 Android 录屏直播
  3. 科技的成就(二十一)
  4. github merge request(MR)流程说明
  5. Serveless 助力新零售 —— 乐凯撒新餐饮服务落地实践
  6. 利用layui实现侧边导航栏
  7. python 网络教育-百度传课_百度传课年度好课集结,学日语趣味十足
  8. 2021年金属非金属矿山提升机操作考试题及金属非金属矿山提升机操作最新解析
  9. 2021年煤矿井下电气报名考试及煤矿井下电气考试资料
  10. 完美世界手游服务器维护时间表,完美世界手游新区开服表 新区开服时间分享[视频][图]...