SQLAlchemy ORM有一些工具可以简化你的任务。看起来您必须重新发明已经存在于 ORM 层中的一些轮子:“我有一个名为 getuser 的方法,它在 db 中查找用户(按名称或 id),检索用户行,并封装它与用户类” - 这就是 ORM 所做的。
使用 ORM,您有一个 Session,除了其他东西之外,它还用作 ORM 对象的缓存,因此您可以避免在每个事务中多次加载相同的模型。您会发现无论如何都需要加载 User 对象来验证请求,因此根本不查询表可能不是一种选择。
您还可以配置一些属性为延迟加载,这样一些很少需要或笨重的属性只有在您访问它们时才会加载
您还可以将关系配置为在单个查询中快速加载,这可以使您免于执行数百个小的单独查询。我的意思是,在您当前的设计中,以下代码将启动多少个查询:
for user in get_all_users():
print user.get_avatar_uri()
print user.get_name()
print user.get_about()
从您的描述看来,它可能需要 1 + (num_users*3) 次查询。使用 SQLAlchemy ORM,您可以在单个查询中加载所有内容。
结论是:通过主键从数据库中获取单个对象是一种相当便宜的操作,除非您正在构建 facebook 大小的东西,否则您不应该担心这一点。您应该担心的是进行数百个小的单独查询,而一个较大的查询就足够了。这是 SQLAlchemy ORM 非常非常好的领域。
现在,关于“必须创建一个用户对象,并在用户甚至不使用检索到的数据时查找用户行,这难道不是一种浪费;而只是想对列的子集进行更改”-我理解你正在考虑类似的事情
class ChangePasswordForm(...):
def _change_password(self, user_id, new_password):
session.execute("UPDATE users ...", user_id, new_password)
def save(self, request):
self._change_password(request['user_id'], request['password'])
相对
class ChangePasswordForm(...):
def save(self, request):
user = getuser(request['user_id'])
user.change_password(request['password'])
前一个示例将只发出一个查询,后者必须发出一个 SELECT 并构建用户对象,然后发出一个 UPDATE。后者可能看起来“效率高出两倍”,但在实际应用中,差异可能可以忽略不计。此外,您通常需要从数据库中获取对象,或者进行验证(新密码不能与旧密码相同)、权限检查(用户 Molly 是否允许编辑照片 #12343 的描述?)或记录。
如果您认为执行额外查询的区别很重要(数百万用户不断编辑他们的个人资料图片),那么您可能需要进行一些分析并查看瓶颈在哪里。