# 转载自: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. %pylab ipython 中文

    格式:%pylab [--no-import-all] [gui] 该命令会在ipython或notebook环境中自动加载numpy和matplotlib库,跟以下语句功能一致 import num ...

  2. do_try_to_free_pages

    /* * This is the main entry point to direct page reclaim. * * If a full scan of the inactive list fa ...

  3. 【问题解决】Project facet Java version 1.7 (或者1.8)is not supported.

    在移植eclipse项目时,如果遇到 “Project facet Java version 1.7 is not supported.” 项目中的jdk1.7不支持.说明项目是其他版本jdk编译的, ...

  4. apiDoc 入门

    网站 http://apidocjs.com/#demo Install npm install apidoc -g Run apidoc -i myapp/ -o apidoc/ -t mytemp ...

  5. CentOS 服务ftp(vsftpd)

    1.检查是否已经安装vsftpd yum list installed | grep vsftpd 2.安装vsftpd yum install -y vsftpd 3.检查vsftpd system ...

  6. [洛谷P3975][TJOI2015]弦论

    题目大意:求一个字符串的第$k$大字串,$t$表示长得一样位置不同的字串是否算多个 题解:$SAM$,先求出每个位置可以到达多少个字串($Right$数组),然后在转移图上$DP$,若$t=1$,初始 ...

  7. POJ.3624 Charm Bracelet(DP 01背包)

    POJ.3624 Charm Bracelet(DP 01背包) 题意分析 裸01背包 代码总览 #include <iostream> #include <cstdio> # ...

  8. Hadoop,大数据,云计算三者之间的关系

    大数据和云计算是何关系?关于大数据和云计算的关系人们通常会有误解.而且也会把它们混起来说,分别做一句话直白解释就是:云计算就是硬件资源的虚拟化;大数据就是海量数据的高效处理.大数据.hadoop及云计 ...

  9. jenkins实现maven项目自动化部署tomcat

    最近公司有用到jenkins实现自动化部署,这里我对新的东西也是比较感兴趣,就用了点时间尝试了一下,虽然网上有很多这种例子,但是可能有些细节我也走了一些弯路.在这里记录一下,方便下次用到. 实现环境: ...

  10. noip模拟赛 但有用

    题目描述 给定一个 n ∗ m 个矩阵,矩阵中每个数都是 [1, 12] 内的整数.你可以执行下列两个操作任意多次: • 指定一行,将该行所有数字 +1. • 指定一列,将该列所有数字 +1. 如果执 ...