• Django ORM 事务和查询优化


    一、事务操作


    模块 from django.db import transaction

    1 开启事务:with transaction.atomic()

    from django.db import transaction
    class MyView(View):
        def post(self, request):
            ### 在with代码块中开启事务,出了with自动结束事务
            with transaction.atomic()
            	pass

    开启事务:@transaction.atomic

    class MyView(View):
        @transaction.atomic
        def post(self, request):
            ### 整个post方法都在事务中
            pass

    2 设置事务回滚点

    ### 可以设置多个
    sid = transaction.savepoint()

    事务回滚

    ### 回滚整个事务  但是不能在自动提交的事务中使用
    transaction.rollback() 
    
    ### 回滚到 sid
    transaction.savepoint_rollback(sid)

    3 事务提交

    ### 提交整个事务  但是不能在自动提交的事务中使用
    transaction.commit() 
    
    ### 释放保存点 sid ,自保存点被创建依赖执行的更改成为事务的一部分
    transaction.savepoint_commit(sid)
    
    ### atomic的事务,只有在事务结束后,才会自动提交到数据库,进行数据的持久化

    4 设置事务隔离

    配置文件

    import psycopg2.extensions
    
    ### 根据需要设置隔离级别,如下配置是READ_COMMITTED
    ### 但是配置PostgreSQL,不能配置mysql,否则会报错
    DATABASES = {
        ### ...
        'OPTIONS': {
            'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED,
        },
    }

     

    二、ORM 惰性查询

    即尽量减少对数据库的操作,减轻数据库的压力

    1 ORM惰性查询

    ORM 内所有的 SQL 查询语句,都是惰性操作,即当你需要使用查询结果时,才会真正去执行 SQL 语句访问数据库,否则是不会执行查询的

    可使用代码验证:

    2 配置settings文件,使得当执行 SQL 语句时,在终端打印 SQL 命令

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level': 'DEBUG',
            },
        }
    }

    3 验证

    ### 只查询,不使用查询结果
    models.User.objects.all()
    
    ### 将查询结果赋值给变量res,并使用res
    res = models.User.objects.all()
    print(res)
    
    ### 分别执行,查看终端的打印结果

     

    三、only & defer

    only 查询

    • 指定查询某字段时,将全部结果一次性获取出来,以后再访问该字段数据时,直接从内存中拿即可,不需要再操作数据库,返回QuerySet[obj1, obj2]

    defer 查询

    • 指的是一次性获取指定字段之外的所有字段数据,封装到对象中,以后再访问这些字段数据时,直接从内存中拿即可,不需要再操作数据库
    class UserTest(models.Model):
        id = models.AutoField(primary_key = True)
        name = models.CharField(max_length = 32)
        age = models.IntegerField()
        def __str__(self):
            return 'name: %s, age: %s' %(self.name, self.age)
    
    models.UserTest.objects.create(name = '小慧',age = '18')
    models.UserTest.objects.create(name = '小嘉',age = '19')
    models.UserTest.objects.create(name = '小甜',age = '17')
    models.UserTest.objects.create(name = '小妞',age = '16')
    
    ### all 查询
    ### 访问一次数据库,打印一条sql命令,获取所有的 UserTest 表中的数据
    res = models.UserTest.objects.all()  
    print(res)
    
    ### only 查询
    ### 访问一次数据库,打印一条sql命令,仅仅获取 name 的所有数据到内存
    res = models.UserTest.objects.only("name")  
    print(res)
    
    for user_obj in res:
        print(user_obj.name)  # 直接从内存中获取,不访问数据库,不打印 SQl 命令
        print(user_obj.age)   # 每执行一次,就访问一次数据库,打印一次 SQl 命令
        
    ### defer 查询
    ### 访问一次数据库,打印一条 SQl 命令,获取除了 name 之外的所有数据到内存
    res = models.User.objects.defer("name")  
    for user_obj in res:
        print(user_obj.name)  # 每执行一次,访问一次数据库,打印一条 SQl 命令
        print(user_obj.age)   # 直接从内存中获取,不访问数据库,不打印 SQl 命令

    注意:分别执行才能看到效果注释 print

     

    四、select_related & prefetch_related

    都支持正反向跨表查询,规则等同于基于对象的正反向查询,正向:'外键',反向:'表名小写_set'

    select_related:指定外键,连表查询(inner join),获取所有数据到内存,不能指定多对多关系的外键

    res = models.Book.objects.select_related('publish')

    prefetch_related:指定外键,先查询本表所有数据,再根据外键查询对应的数据表所有数据,相当于子查询,可以指定多个外键,即多个子查询

    res = models.Book.objects.prefetch_related('publish')

     

  • 相关阅读:
    md-editor-v3 markdown编辑器
    小土堆-pytorch-神经网络-搭建小实战和Sequential 09_笔记
    Reinforcement Learning 强化学习(四)
    论文阅读 Memory Enhanced Global-Local Aggregation for Video Object Detection
    11、JavaWeb启程——会话跟踪技术Cookie&Session
    MIB 6.1810实验Xv6 and Unix utilities(5)find
    怎样使用浏览器静默打印网页
    “闭关修炼”这么久,吃透这些“微服务”笔记,足够面试涨10K
    Python笔记3-正则表达式
    SSL证书抵御企业网络攻击的风险
  • 原文地址:https://www.cnblogs.com/huaxiayuyi/p/16720421.html