# 转载自: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. HTML5拖拽表格中单元格间的数据库

    效果图:

  2. BZOJ 2120 数颜色(树状数组套主席树)

    1A啊,激动. 首先,不修改的情况下可以直接用主席树搞,修改的话,直接用主席树搞一次修改的情况下复杂度是O(nlogn)的. 就像你要求区间和一样,用前缀和查询是O(1),修改是O(n),只不过主席树 ...

  3. HDU 4869 Turn the pokers(思维+逆元)

    考试的时候没有做出来... 想到了答案一定是一段连续的区间,一直在纠结BFS判断最后的可行1数. 原来直接模拟一遍就可以算出来最后的端点... 剩下的就是组合数取模了,用逆元就行了... # incl ...

  4. 【转】PowerDesigner中Table视图同时显示Code和Name

    为避免图片失效,文字描述, Tools-Display Preference-->左侧Table-->右下角Advanced-->左侧树Columns-->右侧上面第一个放大镜 ...

  5. [洛谷P4111][HEOI2015]小Z的房间

    题目大意:有一个$n\times m$的房间,一些位置是房间,另一些位置是柱子,相邻两个房间之间有墙,问有多少种方案可以打通一些墙把所有房间连成一棵树,柱子不可以打通 题解:矩阵树定理,把房间当点,墙 ...

  6. POJ2186:Popular Cows——题解

    http://poj.org/problem?id=2186 题面纯英文--就不粘题面了. 简单的说,就是将图强连通分量缩点,然后拓扑一下. 为了避免拓扑,我们可以反向存图,然后查入度为0的点即可. ...

  7. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur 解题报告

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 约翰有\(n\)块草场,编号1到\(n\),这些草场由若干条单行道相连.奶牛贝西是美味牧草的鉴赏家,她想到达尽可 ...

  8. 20165218 学习基础和C语言基础调查

    个人技能及阅读心得 个人技能之绘画 绘画是我从很小便开始接触的,从最初的简笔画到国画.素描.水粉,大约也学了七八年.但是到了高中之后,就逐渐放下了. 记得当初学素描时,老师的一句话让我记忆犹新,她说, ...

  9. UVA.10305 Ordering Tasks (拓扑排序)

    UVA.10305 Ordering Tasks 题意分析 详解请移步 算法学习 拓扑排序(TopSort) 拓扑排序的裸题 基本方法是,indegree表示入度表,vector存后继节点.在tops ...

  10. Linux环境下用Weblogic发布项目【一】 -- 安装Weblogic

     一.Weblogic安装系统环境: 1.前提条件: a.在笔记本[Windows7]上安装远程连接Linux软件:F-Secure SSH File Transfer Trial[简写为:FSSH] ...