# 转载自:https://www.cnblogs.com/miaojiyao/articles/5217757.html
下面讨论一下用peewee的些许提高性能的方法。 避免N+1查询 N+1查询指的是当应用提交一次查询获取结果,然后在取得结果数据集的每一行时,应用至少再次查询一次(也可以看做是嵌套循环)。 大多数情况下,n 查询可以通过使用SQL join或子查询来避免。数据库本身可能做了嵌套循环,但是它比在你的应用代码本身里做这些n查询更高效,后者通常会导致与数据库再次潜在通讯,没有利用数据库本身关联和执行子查询时会进行切片等优化工作。 Peewee提供了几种API去减轻N+1查询的行为。再看看贯串我们这篇文档的模型,User和Tweet,这部分我们重点讲一下一些N+1场景,说明peewee怎么帮助我们避免N+1查询。 在一些场景里,N+1查询不会明显表现为显著地或可测量的性能瓶颈点。它也由你要查询的数据,使用的数据库本身,以及执行查询获取结果的潜在因素。优化前后可以测试性能,确保和你预测的变化相同。 raw执行时也会出现这种情况:
### all_res = Results.raw(sql, "2012", "2013","2014", "2015") 列出最近的tweets tweets时间轴显示最近用户的tweets。除了tweet的内容,还要显示tweet作者的用户名。N+1场景描述为: 获取最近的10条tweets
每个tweet,查询作者信息(10次查询)
通过用join选择两个表,peewee使得在一次查询里完成任务: 复制代码
query = (Tweet
.select(Tweet, User) # Note that we are selecting both models.
.join(User) # Use an INNER join because every tweet has an author.
.order_by(Tweet.id.desc()) # Get the most recent tweets.
.limit(10)) for tweet in query:
print tweet.user.username, '-', tweet.message
复制代码
没有用join时,得到tweet.user.username会触发一次查询去解析外键tweet.user从而得到相关联的user。 由于我们在User上关联并选择,peewee自动为我们解析外键。 列出所有用户和他们的tweets 你想要显示若干用户和他们所有的tweets的页面。N+1场景为: 取得些许用户。
每个用户取到他们的tweets。
虽然和上个例子相似,但是重要区别是:我们选择tweets时,每个tweet只有一个关联的用户,所以可以直接赋值到外键, 反过来不对,因为一个用户可有任意数量tweets或者没有。 Peewee提供两两种途径去避免O(n)查询: 1.首先取到用户,然后取到关联这些用户的所有tweets。一旦peewee取到tweets,将它们与合适的用户匹配。 这种方法通常很快,但是会在所选择的每个表上执行一次查询。 2.在一个查询里得到用户和tweets。用户数据将复制,所以peewee将在列举结果集时减少重复和聚合tweets。 这种方法导致有许多数据需要传输,并且要有许多python逻辑去减少行重复。 每种方案根据查询数据的大小和结构都会可能比另一种更好。 使用prefetch peewee使用子查询可以预获取数据。这种方法需要prefetch特殊API使用。Pre-fetch,像其名字本身, 用子查询去急切加载给定用户的相应的tweets。意味着我们用O(k)查询K张表而不是O(n)查询n行纪录。 下面演示我们如何得到若干用户和他们最近一周的tweets: 复制代码
week_ago = datetime.date.today() - datetime.timedelta(days=7)
users = User.select()
tweets = (Tweet
.select()
.where(
(Tweet.is_published == True) &
(Tweet.created_date >= week_ago))) # This will perform two queries.
users_with_tweets = prefetch(users, tweets) for user in users_with_tweets:
print user.username
for tweet in user.tweets_prefetch:
print ' ', tweet.message
复制代码
注意User 查询和Tweet查询都没有JOIN子句,当我们使用prefetch时不必指名join prefetch可以用于任意数量的表。可以查看API文档看其他例子。 用prefetch时应考虑的事情: 预查询的模型必须存在外键
通常它比aggregate_rows方法更高效
因为数据没有重复的所以传输的数据更少
因为不用减重复所以python逻辑更少
当你想要在最外的查询里使用LIMIT没问题,但是可能正确的实现限制子查询的返回结果大小有些困难。
使用aggregate_rows aggregeate_rows一次在内存中减少重复,选择所有的数据。它和prefetch都可以完成任意复杂的查询。 使用这个特性需要当创建查询时用到特殊的标志aggregate_rows。它告诉peewee减少那些根据JOIN的结构可能会重复的行。 因为在减少重复聚合数据时有许多计算,所以可能使用aggregate_rows可能在一些查询中会比用prefetch性能低,即使面对的是 O(n)简单的 查询时,所以你不确定使用哪种方法时测试检查你的代码。 复制代码
query = (User
.select(User, Tweet) # As in the previous example, we select both tables.
.join(Tweet, JOIN.LEFT_OUTER)
.order_by(User.username) # We need to specify an ordering here.
.aggregate_rows()) # Tell peewee to de-dupe and aggregate results. for user in query:
print user.username
for tweet in user.tweets:
print ' ', tweet.message
复制代码
复制代码
query = (User
.select(User, Tweet) # As in the previous example, we select both tables.
.join(Tweet, JOIN.LEFT_OUTER)
.order_by(User.username) # We need to specify an ordering here.
.aggregate_rows()) # Tell peewee to de-dupe and aggregate results. for user in query:
print user.username
for tweet in user.tweets:
print ' ', tweet.message

peewee外键性能问题的更多相关文章

  1. 通过在Oracle子表外键上建立索引提高性能

    根据我的经验,导致死锁的头号原因是外键未加索引(第二号原因是表上的位图索引遭到并发更新).在以下两种情况下,Oracle在修改父表后会对子表加一个全表锁: 1)如果更新了父表的主键(倘若遵循关系数据库 ...

  2. MS SQL巡检系列——检查外键字段是否缺少索引

    前言感想:一时兴起,突然想写一个关于MS SQL的巡检系列方面的文章,因为我觉得这方面的知识分享是有价值,也是非常有意义的.一方面,很多经验不足的人,对于巡检有点茫然,不知道要从哪些方面巡检,另外一方 ...

  3. 使用Guid做主键和int做主键性能比较

    使用Guid做主键和int做主键性能比较 在数据库的设计中我们常常用Guid或int来做主键,根据所学的知识一直感觉int做主键效率要高,但没有做仔细的测试无法 说明道理.碰巧今天在数据库的优化过程中 ...

  4. MySQL外键之级联

    简介 MySQL外键起到约束作用,在数据库层面保证数据的完整性.例如使用外键的CASCADE类型,当子表(例如user_info)关联父表(例如user)时,父表更新或删除时,子表会更新或删除记录,这 ...

  5. MySQL 外键

    在MySQL中 (1)MySQL 数据表主要支持六种类型 ,分别是:BDB.HEAP.ISAM.MERGE.MYISAM.InnoBDB.这六种又分为两类,一类是”事务安全型”(transaction ...

  6. EntityFramework 外键值映射

    如果在 EF OnModelCreating 中配置了实体外键映射,也就是 SQL Server 中的 ForeignKey,那么我们在添加实体的时候,主实体的主键值会自动映射到子实体的外键值,并且这 ...

  7. 注解:【基于外键的】Hibernate双向1->1关联

    Person与Address关联:双向1->1,[基于外键的]. #主表不应该控制关联关系.(否则会导致生成额外的update语句,从而导致性能下降), #因此主表对应的实体中使用@OneToO ...

  8. MySQL的几个概念:主键,外键,索引,唯一索引

    概念: 主键(primary key) 能够唯一标识表中某一行的属性或属性组.一个表只能有一个主键,但可以有多个候选索引.主键常常与外键构成参照完整性约束,防止出现数据不一致.主键可以保证记录的唯一和 ...

  9. 基于MVC4+EasyUI的Web开发框架经验总结(9)--在Datagrid里面实现外键字段的转义操作

    我们在使用EasyUI的时候,很多情况下需要使用到表格控件datagrid,这个控件控件非常强大,使用起来很简洁,但是我在使用中,发现对于一个表里面的外键字段进行转义,并显示引用表的一些名称的操作,却 ...

随机推荐

  1. jquery计算器(改良版)

    代码: <!Doctype html> <html> <meta charset="UTF-8"> <title>计算器</t ...

  2. IPython 4.0发布:Jupyter和IPython分离后的首个版本

    IPython 4.0日前正式发布,这是IPython分离成IPython和Jupyter后的第一个重要版本. 更新Jupyter的快捷方式是: pip install --upgrade jupyt ...

  3. jenkins部署springboot多项目

    war包的部署问题不大,这里记录jar包的部署过程: 1:jar包的体积过大问题 pom.xml参考以下配置(依赖包会分离到target/lib/,jar包体积由几十M缩小到几k) <build ...

  4. [剑指Offer] 51.构建乘积数组

    题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1].不 ...

  5. 《转》HTTP 协议入门

    HTTP 协议是互联网的基础协议,也是网页开发的必备知识,最新版本 HTTP/2 更是让它成为技术热点. 本文介绍 HTTP 协议的历史演变和设计思路. 一.HTTP/0.9 HTTP 是基于 TCP ...

  6. Retrofit工具类

    package com.example.week2.retrofitUtils; import android.util.Log; import com.example.week2.model.Con ...

  7. openjudge666:放苹果—题解

    (测试这里的markdown,同时也有纪念意义吧--第一次写的题解) 当时刚学递推的时候做的一道题 oj上的666题 666:放苹果 总时间限制: 1000ms 内存限制: 65536kB 描述 把M ...

  8. TCP中三次握手建立和四次握手释放以及相关问题

    本文基于个人所学和网上博文所整理,若有不妥处,欢迎留言指出 TCP连接过程中标志位的意义: 字符缩写 描述 SYN 同步序号,表示此报文是一个连接请求或连接接受报文 ACK 确认位,对接收到的报文的确 ...

  9. C++中swap函数

    本文是我用到swap函数时,对其产生好奇,所以结合网上有关博文写下的.个人水平有限,若有错误的地方,欢迎留言指出.谢谢! 一.通用的函数交换模板 template<class T> voi ...

  10. 洛谷 P2657 [SCOI2009]windy数 解题报告

    P2657 [SCOI2009]windy数 题目描述 \(\tt{windy}\)定义了一种\(\tt{windy}\)数.不含前导零且相邻两个数字之差至少为\(2\)的正整数被称为\(\tt{wi ...