Django ORM 实现和惰性查询优化
1。操作
Module 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.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,
},
}
2. 惰性 ORM 查询
即减轻数据库中的工作,缓解惰性 ORM 压力
# 提交整个事务 但是不能在自动提交的事务中使用
transaction.commit()
# 释放保存点 sid ,自保存点被创建依赖执行的更改成为事务的一部分
transaction.savepoint_commit(sid)
# atomic的事务,只有在事务结束后,才会自动提交到数据库,进行数据的持久化
4 所有 ORM 中的 SQL 查询语句为惰性操作,即当需要使用查询结果时,才会真正执行SQL语句来访问数据,否则请求将无法得到满足。
可以使用代码验证:
2 配置配置文件,以便在执行 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)
# 分别执行,查看终端的打印结果
仅并延迟
3.仅问题
- 当您指定要询问的字段时,所有答案将立即可用。以后访问现场数据时,可以直接从内存中访问。不再需要操作数据库。返回 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 命令
注意:单独进行 要查看结果,请注意打印
IV。 select_lated 和 prefetch_lated
都支持表匹配查询。这些规则类似于基于对象的来回问题。正向:'外键',反向:'子表名称_集'
select_lated:插入外键,插入表查询(内连接),将所有数据插入内存,多连接的外键不可用。
res = models.Book.objects.select_related('publish')
prefetch_lated:设置一个外键,先查询这个表中的所有数据,然后根据外键查询对应数据表中的所有数据。它类似于子查询。可以定义多个外键,即多个子查询
res = models.Book.objects.prefetch_related('publish')
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。