V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
rogwan
V2EX  ›  Python

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

  •  
  •   rogwan · 2016-06-22 21:21:43 +08:00 · 4425 次点击
    这是一个创建于 2866 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如: session.query(Artile).all() 和 Select * from articles ,这两种做法,对内存占用的大小有区别吗?

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

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

    上面例子虽然有点极端,实际情况加 filter 条件筛选 Article 查询出来的数据量也非常大。
    通常这种情况,大家选择什么样的解决方式啊?
    15 条回复    2016-06-23 11:55:43 +08:00
    loading
        1
    loading  
       2016-06-22 21:24:44 +08:00 via Android
    Orm 带来的特性,付出一点点内存,值得!
    loading
        2
    loading  
       2016-06-22 21:25:37 +08:00 via Android
    而且,复杂的 SQL,很多人写出来比 orm 的性能要差。
    rogwan
        3
    rogwan  
    OP
       2016-06-22 21:30:24 +08:00
    @loading 嗯,一般情况下这个必须是值得的。就是遇到 Article 这种对象,有文章的内容( text 类型),可能一篇文章记录就几十 K 啊。比如查询出来用户关注的文章, 1 个用户关注 1000 个人,想象下 1 万个用户,那内存得要多大啊?
    loading
        4
    loading  
       2016-06-22 21:37:38 +08:00 via Android
    就你这样玩,直接写 SQL 更不行…
    msg7086
        5
    msg7086  
       2016-06-22 21:47:51 +08:00
    好点的 ORM 可以分段读取吧。 Python 不熟,但是至少数据分页查询不是个很难的事情。
    ChiChou
        6
    ChiChou  
       2016-06-22 22:03:29 +08:00
    @rogwan 你为什么不分页?对应的就是 limit
    rogwan
        8
    rogwan  
    OP
       2016-06-22 23:03:17 +08:00
    @ChiChou @NearTan 主要是因为要把这些 Articles 先全部取出来,再根据 author/ip/post_time 等等做多重运算后,再 remove 一些数据。分页只能放在最后呈现的阶段啊。(当然,也可以把这些多重运算,在数据库中用 SQL 语言先解决,这个就是前面提到的,担心复杂的 sql 语句效率的问题)
    NearTan
        9
    NearTan  
       2016-06-22 23:11:33 +08:00
    @rogwan yield_per 用到的是迭代器,跟分页没关系
    仔细看了一下你的需求,你的「多重运算」感觉可以通过 SQLAlchemy 层来解决
    rogwan
        10
    rogwan  
    OP
       2016-06-22 23:21:13 +08:00
    @NearTan "SQLAlchemy 层",你是指用 ORM 的 xxx.query.filter(www.query.filter(www.query.filter()))这样的嵌套查询吗?
    rogwan
        11
    rogwan  
    OP
       2016-06-22 23:28:20 +08:00
    yield_per 倒是一个看起来可以平衡内存占用和 SQL 查询效率的一个方式,以前没有用过,可以尝试下实际的运行效率好不好。
    daybyday
        12
    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
        13
    rogwan  
    OP
       2016-06-23 11:25:03 +08:00
    @daybyday 谢谢!负载过重的话,这是个可行的方式
    sfree2005
        14
    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
        15
    rogwan  
    OP
       2016-06-23 11:55:43 +08:00
    @sfree2005 看起来你这个“粗暴”的方法是很实用的,哈哈。是分库分表的思路啊。其实 Article 表里就是内容 content ( text 类型)占空间,其他的字段全部导到内存里也没多大。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   863 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:14 · PVG 05:14 · LAX 14:14 · JFK 17:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.