SQLAlchemy:通过主键高效/更好的查询?

3 投票
3 回答
4166 浏览
提问于 2025-04-15 21:36

我正在使用MySQL。

我有一个用户表,采用声明式模式:

class User(Base):
    __tablename__ = 'user'
    id = Column(u'id', Integer(), primary_key=True)
    name = Column(u'name', String(50))

当我有一串用户标识符时,我会用以下方式来获取它们:

user_ids = [1, 2, 3, 4, 5]
users = Session.query(User).filter(User.id.in_(user_ids)).all()

我不喜欢使用 in_,因为我觉得我学过它在索引字段上的性能不好。这是真的吗?

有没有更好的方法来做这个查询?我该如何用 OR 来写这个查询,使用SQLAlchemy?

3 个回答

0

@Hadrien(提问者)使用了:

from sqlalchemy.sql.expression import or_
user_ids = [1, 2, 3, 4, 5]
clauses = or_( *[User.user_id==x for x in users] )
users = Session.query(User).filter(clauses).all()
4

很多性能问题和数据库引擎有关系。接下来这部分内容主要讲的是MySQL。

在使用IN()这个条件时,如果是在一个有索引的字段上,可能会导致性能不太好,但在你给出的例子中不会有这个问题。对于一定数量的user_ids,你的查询会是最快的。不过,当user_ids的数量达到某个点时,把这些ID放到一个临时表里,然后进行join操作会更快。想了解更多关于IN()和临时表在MySQL中性能对比的内容,可以查看这篇文章:"MySQL中的参数传递:IN列表与临时表"。

如果这些user_ids是根据用户的某些特征(比如是管理员或者无效用户)来决定的,你可以在用户表中添加一个字段,这样就可以完全避免这个问题。

3

使用 in 语句的另一种选择是用 or 来连接多个 ID:

id = 1 or id = 2 or id = 3

如果你只有几个 ID,这样做可能会让速度更快一些。

根据 "常见过滤操作符" 的说明:

from sqlalchemy import or_
filter(or_(User.name == 'ed', User.name == 'wendy'))

你没有说你用的是什么数据库,但你的管理员可能是你最好的帮手。了解使用什么语句的最佳方法是分析查询,并尝试几种不同的方式,这样你就能知道你的数据库引擎对这些方式的处理效果如何。无论你使用什么数据库,只要它支持 orin,那么使用这些方式通常会比一个个查询所有 ID 更快。

其实,担心用 in 还是其他语句,可能对整个应用的速度影响不大,相比之下,改动代码的其他部分可能会更有效。现在的数据库引擎在优化简单查询方面做得相当不错,只要你的查询合理,就能获得良好的性能。

我们在编程中需要学习的一件事是,先让代码正常工作,然后再测试和优化,如果有问题的话。我们常常以为知道瓶颈在哪里,但使用性能分析工具可能会让我们发现其实并不是这样。使用性能分析器和基准测试工具可以帮助我们找出问题所在,并显示出加速需要调整的最佳方法。

撰写回答