from django.db import connection
print connection.queries
即可看到sql语句以及对应的时间
2.写代码需要注意的小技巧
所有技巧的根本原因:QuerySets是惰性的,会延迟到使用它的值时,才执行sql语句查数据。之前仅仅准备好sql语句,并不会立即执行。
例如
xxxs = XXX.object.all()只要你不使用xxxs里面的值或其他属性,不会执行sql语句。 print xxxs此时才执行sql语句。 2.1使用缓存
# 这样的QuerySet没有被缓存 print([e.headline for e in Entry.objects.all()]) print([e.pub_date for e in Entry.objects.all()]) # 这么做使用缓存 entries = Entry.objects.all() print([e.headline for e in entries])print([e.pub_date for e in entries])
2.2对于某个对象,只会缓存属性,不会缓存方法>>> news = News.objects.get(id=1) >>> news.channel # 此时的channel对象会从数据库取出 >>> news.channel # 这时的channel是缓存的版本,不会造成数据库访问>>> news.authors.all() # 执行查询 >>> news.authors.all() # 再次执行查询 2.3在模板(如HTML)中使用缓存 {% with aaa=Entry.objects.all() %} {% 使用变量 aaa %}{% 使用变量 aaa %} #只会查询一次
2.4 大量数据迭代 使用 iterator()
2.5 预加载数据
QuerySet.select_related().fliter(),针对foreign key 和 one-to-onenews = News.objects.select_related().get(id=372924135) print news.channel # 不会访问数据库,使用预加载数据QuerySet.prefetch_related() ,1.4中存在, 和select_related()类似,针对many-to-many
2.6 不要查询用不着的字段,使用QuerySet.values() 和 values_list()只获取需要使用的字段,特别是blog等类型,不要轻易加载
类似的有QuerySet.defer() 来延迟加载某字段,真正加载时会产生额外查询。QuerySet.only() 只加载某字段,之后读取任何其他属性都会产生查询。
2.7 如果你只是想要获取有多少数据,不要使用 len(queryset),使用queryset.count()
如果你只是想要知道是否至少存在一个结果,不要使用 if querysets, 使用queryset.exists()
如果你只是想要使用外键的id,不要如 news.channel.id, 而是 news.channel_id
反过来,外键反向取集合,不要额外查询,使用_set.例如:
A有一个外键字段b,指向B。从A取B, a.b; 从B取A, b.a_set.all(), 不要A.objects.filter(b=b)
批量更新使用 QuerySet.update() 批量删除使用 QuerySet.delete()批量创建对象用 django.db.models.query.QuerySet.bulk_create() 特别是多对多关系不要单个插入,多对多应该诸如add(obj1,obj2,.....objn)操作, 或者直接xxxmodel.manytomanyfield = [obj1, obj2, ...... objn],此表达式其实django内部分两步实现,第一步清空clear()该多对多字段,然后批量插入后面列表所赋的值 多对多操作参见官网https://docs.djangoproject.com/en/1.5/topics/db/examples/many_to_many/ 多对多采用model form只需要注意 save()方法的 commit 问题,详见https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#the-save-method 如不嫌弃,也可以看看鄙人另一篇《关于django model form》 此外 此文章翻译了基于1.4的官方文档数据库优化部分http://the5fire.com/django-database-access-optimization.html