Django ORM 数据库管理 提高查询、更新性能的技巧和编程习惯:

在Django中使用ORM进行数据库管理时,以下是一些提高数据查询、更新和插入效率的技巧和编程习惯:

1. 索引优化 - 效果最显而易见

  • 为常用的查询字段(如外键、唯一字段等)添加数据库索引,可以显著提高查询速度。
python 复制代码
class Book(models.Model):
    title = models.CharField(max_length=255, db_index=True)

以下是一个很常见的例子(并非极端条件才发生):在配置低的服务器上,表格TableA 的记录数10w,字符串字段K无索引,一个简单查询耗时10秒,一个插入耗时50毫秒。如果K建立索引,查询耗时降可到毫秒级别,插入耗时增加也只是毫秒级别。总体上,索引带来的查询性能提升(10秒级)会远远大于插入性能的下降(毫秒级)。

2. 使用only()defer()

  • only():仅加载指定字段,用于降低内存占用和传输开销。
  • defer():延迟加载某些字段,适用于大字段,如Blob或TextField。

> 如果表中字段类型较小(例如都是int类型),而且返回的数据条数很少,其实可以忽略不使用.only()带来的性能差异。

> 如果表中的字段是大数据类型(如长字符串或BLOB),应使用.only()来优化查询

复制代码
# Example of only()
users = User.objects.only('id', 'username').all()

# Example of defer()
books = Book.objects.defer('description').all()

3. 合理使用批量操作

  • 批量插入 :使用bulk_create(),可以一次性插入多条数据,减少数据库的连接和提交次数。
  • 批量更新 :使用bulk_update(),高效更新多条记录。
  • 批量删除 :使用delete()而不是逐条删除。
python 复制代码
# Example of bulk_create()
Book.objects.bulk_create([
    Book(title='Book 1'),
    Book(title='Book 2'),
    Book(title='Book 3')
])

# Example of bulk_update()
books = Book.objects.filter(published=False)
for book in books:
    book.published = True
Book.objects.bulk_update(books, ['published'])

4. 分页查询

  • 对大量数据进行分页处理,避免一次性加载过多数据,占用内存资源。使用Paginator类或iterator()方法来进行分页和流式处理。

    python 复制代码
    from django.core.paginator import Paginator
    
    books = Book.objects.all()
    paginator = Paginator(books, 10)  # 每页10条数据
    page_1_books = paginator.get_page(1)

5. 使用事务(Transactions)

  • 对于多条相关操作(如插入、更新、删除),使用事务来保证数据一致性和操作的原子性,同时避免多次提交的开销。

    python 复制代码
    from django.db import transaction
    
    with transaction.atomic():
        author = Author.objects.create(name='Author')
        book = Book.objects.create(title='Book', author=author)
  1. 使用原生SQL和原生查询(Raw Queries)
  • 对于极其复杂或高性能要求的查询,使用Django的raw()方法执行原生SQL语句,或者使用RawSQL来插入自定义SQL。
python 复制代码
from django.db import connection

books = Book.objects.raw('SELECT * FROM book WHERE title = %s', ['Django'])

7. get()filter()的使用 -- 效率其实差不多

如果可以确保匹配结果有且只有一个(即无需处理异常),get()通常略微更高效,但几乎可以忽略不计。对于非预期结果的处理filter().first()通常更轻松,由于不需要try,代码更简洁,可读性更强。

python 复制代码
# Efficient way to get the first matched record
book = Book.objects.filter(title='Django').first()

8. 使用Q对象和F表达式

  • Q对象:用于组合复杂的查询条件。

  • F表达式 :允许在查询或更新时直接引用字段的值,避免多次读取数据库,提高更新操作效率。

    python 复制代码
    from django.db.models import Q, F
    
    # Example of Q object
    books = Book.objects.filter(Q(title__icontains='Django') | Q(author__name='John'))
    
    # Example of F expression
    Book.objects.filter(id=1).update(page_count=F('page_count') + 1)

    9. 缓存查询结果

  • 对于频繁使用但不经常变动的数据,可以使用缓存来减少数据库访问次数。Django内置的缓存框架支持多种缓存机制,如内存、文件、数据库等。

python 复制代码
from django.core.cache import cache

books = cache.get('all_books')
if not books:
    books = Book.objects.all()
    cache.set('all_books', books, 60*15)  # 缓存15分钟

10. 使用select_related()prefetch_related()

  • select_related():用于减少多表查询的数量,适合在一对一或外键关系中使用。它在单个SQL查询中加入JOIN操作,加载相关表的数据。
  • prefetch_related():适合多对多或反向外键关系,用于预取相关对象并减少SQL查询数量。
  • 巧妙地组合使用这两个方法,减少N+1查询问题。
python 复制代码
# Example of select_related()
books = Book.objects.select_related('author').all()

# Example of prefetch_related()
authors = Author.objects.prefetch_related('books').all()
相关推荐
Ulyanov3 分钟前
Apache Kafka在雷达仿真数据流处理中的应用
分布式·python·kafka·apache·雷达电子战
u0109147608 分钟前
CSS如何处理超长文本换行问题_结合word-wrap属性
jvm·数据库·python
电化学仪器白超12 分钟前
小乌龟Git全程图形化操作指南:嵌入式本地版本管理与Gitee私有云备份实战
git·python·单片机·嵌入式硬件·物联网·gitee·自动化
2401_8371638913 分钟前
如何在 Go 中正确解析带命名空间的 SOAP 响应
jvm·数据库·python
_Evan_Yao13 分钟前
RAG中的“Chunk”艺术:我试过10种切分策略后总结的结论
java·人工智能·后端·python·软件工程
m0_3776182314 分钟前
CSS如何处理溢出隐藏_使用overflow-hidden与盒模型
jvm·数据库·python
月巴月巴白勺合鸟月半17 分钟前
Delphi 开发避坑终极指南:数据库 Decimal (18,6) 类型选择,别再用错 Double 和 Currency!
数据库
qq_50242899034 分钟前
清华大学与微软亚洲研究院出品:Kronos 本地部署教程
数据结构·python·金融量化·kronos开源模型
techdashen37 分钟前
一个徽章坏了,顺带扯出了 2.3 万个 feature
数据库·mysql
2301_8148098639 分钟前
CSS Grid布局如何解决图片溢出网格单元_设置object-fit与网格尺寸.txt
jvm·数据库·python