我应该最小化Pony ORM中db_session的使用吗?

时间:2019-03-14 17:35:39

标签: python orm database-connection ponyorm premature-optimization

我想知道是否应该最小化db_session的使用?让我们考虑以下两个等效示例:

A)

def do_stuff():
    with db_session:
        task = orm.make_proxy(Task.select().first())
        task.mark_started()
    ...
    this_function_might_take_a_long_time(task)
    ...
    with db_session:
        task.mark_done()

B)

@db_session
def do_stuff():
    task = Task.select().first()
    task.mark_started()
    commit()
    ...
    this_function_might_take_a_long_time(task)
    ...
    task.mark_done()

通过阅读文档,我可以看出Pony doesn't encourage微观管理db_sessions

With this code each of view function you will define will be wrapped with db_session so you should not care about them.

但是,here 它表明打开它可能会产生成本(编辑:没有,请阅读答案)

Before sending the first query, Pony gets a database connection from the connection pool.

我是否正确地说,B之外的任何东西都是过早的优化,而仅在有限的数据库连接计数情况下才应考虑A?

1 个答案:

答案 0 :(得分:1)

Pony ORM作者Alexander Kozlovsky @metaprogrammer在Official Pony ORM Telegram chat中回答了这个问题。


db_session的目的是管理三件事:

数据库连接

Pony将单独的连接关联到每个线程。如果进程不使用线程,则将仅使用一个连接。 db_session结束时,它将其连接返回到连接池。这意味着连接保持打开状态并保留以备将来使用。下一个db_session将使用相同的连接。因此,就连接用法而言,单个db_session和多个顺序的db_session之间没有区别

交易状态

db_session结束时,它将执行隐式提交。隐式提交和显式提交之间没有区别,因此,如果您有一个通过手工commit()调用的db_session,则它与多个顺序的db_sessions相同。但是,如果您不使用显式commit(),那么长db_session可能会持有数据库锁并阻止其他进程在执行提交之前使用数据库或特定表

已加载对象的内存缓存

单个db_session和多个顺序的db_sessions之间的主要区别在于管理从数据库加载的对象的内存中高速缓存。每个db_session具有单独的缓存。缓存中的对象通过关系进行交叉链接。如果加载一堆课程,学生和小组对象,它们都将通过关系属性相互链接。因此,不可能从缓存中卸载某些对象并保留其余对象。垃圾收集器不能仅从高速缓存中收集某些对象,因为它们都使用循环引用相互指向。因此,只有在db_session完成后才能整体删除高速缓存。 因此,如果您只有一个长期存在的db_session,它将在结束之前不会释放内存。但是,几个较小的db_session可能需要多次从数据库加载同一对象。因此,需要在内存/性能之间进行权衡

P.S。即使db_session完成,连接仍将保持到程序结束或显式db.disconnect()调用。仅当db_session中的某些数据库异常导致回滚时,Pony才会隐式关闭连接。