用 SQLAlchemy 的 query 查询出来的对象,和硬写 SQL 语句查出来的数据对象,内存占用大小有区别吗?

2016-06-22 21:21:43 +08:00
 rogwan
比如: session.query(Artile).all() 和 Select * from articles ,这两种做法,对内存占用的大小有区别吗?

现在的问题是:遇到要做数据查询、过滤、分析 -> 根据分析结果再去查询、过滤、分析,这样的逻辑复杂的多重嵌套运算,不知道用那种方式比较好。

1 、一种方式,是多依赖数据库用 SQL 条件嵌套查询。这样会担心数据库负载重, sql 语句查询效率低。
2 、另外一种方式,就是先把数据对象导到内存里,通过迭代遍历,嵌套计算。这样又担心可能一条语句 session.query(Artile).all()就把内存吃光了。

上面例子虽然有点极端,实际情况加 filter 条件筛选 Article 查询出来的数据量也非常大。
通常这种情况,大家选择什么样的解决方式啊?
4537 次点击
所在节点    Python
15 条回复
loading
2016-06-22 21:24:44 +08:00
Orm 带来的特性,付出一点点内存,值得!
loading
2016-06-22 21:25:37 +08:00
而且,复杂的 SQL,很多人写出来比 orm 的性能要差。
rogwan
2016-06-22 21:30:24 +08:00
@loading 嗯,一般情况下这个必须是值得的。就是遇到 Article 这种对象,有文章的内容( text 类型),可能一篇文章记录就几十 K 啊。比如查询出来用户关注的文章, 1 个用户关注 1000 个人,想象下 1 万个用户,那内存得要多大啊?
loading
2016-06-22 21:37:38 +08:00
就你这样玩,直接写 SQL 更不行…
msg7086
2016-06-22 21:47:51 +08:00
好点的 ORM 可以分段读取吧。 Python 不熟,但是至少数据分页查询不是个很难的事情。
ChiChou
2016-06-22 22:03:29 +08:00
@rogwan 你为什么不分页?对应的就是 limit
NearTan
2016-06-22 22:26:59 +08:00
rogwan
2016-06-22 23:03:17 +08:00
@ChiChou @NearTan 主要是因为要把这些 Articles 先全部取出来,再根据 author/ip/post_time 等等做多重运算后,再 remove 一些数据。分页只能放在最后呈现的阶段啊。(当然,也可以把这些多重运算,在数据库中用 SQL 语言先解决,这个就是前面提到的,担心复杂的 sql 语句效率的问题)
NearTan
2016-06-22 23:11:33 +08:00
@rogwan yield_per 用到的是迭代器,跟分页没关系
仔细看了一下你的需求,你的「多重运算」感觉可以通过 SQLAlchemy 层来解决
rogwan
2016-06-22 23:21:13 +08:00
@NearTan "SQLAlchemy 层",你是指用 ORM 的 xxx.query.filter(www.query.filter(www.query.filter()))这样的嵌套查询吗?
rogwan
2016-06-22 23:28:20 +08:00
yield_per 倒是一个看起来可以平衡内存占用和 SQL 查询效率的一个方式,以前没有用过,可以尝试下实际的运行效率好不好。
daybyday
2016-06-23 10:19:48 +08:00
"根据 author/ip/post_time 等等做多重运算"
如果这些字段可以抽象出一条计算公式,那么可以在更新 article 记录的时候,用这些字段计算出最终值。使用 redis zset 来存储 /缓存,最终值为 zset 的 score , article_id 为 zset 的 member 。需要获取分页的时候,先从 redis zset 取分页 id 集,再从数据库取数据
rogwan
2016-06-23 11:25:03 +08:00
@daybyday 谢谢!负载过重的话,这是个可行的方式
sfree2005
2016-06-23 11:41:51 +08:00
@daybyday 的方法是一个方向,在他方法的基础上你还可以参考这篇文章,看看如果要 filter 各种数据的话, redis 应该做怎样的设计。
文章链接: https://robots.thoughtbot.com/redis-set-intersection-using-sets-to-filter-data
有一点难度,但用好了 filter 的速度很快。

还有一种可能比较粗暴, 没有那么好, 但还算简单的方法。
我假设你 Article 内容本身不在你的要计算和分析的范围,那就可以将 Article id 和各种需要计算和 filter 的 column 单独放个 table , 每次只是查询那个 table ,过滤、分析得到 id 集之后分页, 接着再去查那个真正的 Article table , 这样内存的占用应该少很多了。
rogwan
2016-06-23 11:55:43 +08:00
@sfree2005 看起来你这个“粗暴”的方法是很实用的,哈哈。是分库分表的思路啊。其实 Article 表里就是内容 content ( text 类型)占空间,其他的字段全部导到内存里也没多大。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/287639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX