SQLAlchemy:主键有效/更好的选择?

时间:2010-04-14 20:04:22

标签: python sqlalchemy

又一个新手问题......

假设我在声明模式下有一个用户表:

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

当我有一个用户标识符列表时,我从db获取它们:

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

我不喜欢使用in_,因为我认为我在索引字段上表现不佳 (是真/假?)。

无论如何,有更好的方法来进行查询吗?

谢谢!

编辑:我正在使用MySQL

如何使用OR与sqlalchemy编写此查询?

重新编辑:得到它:

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()

3 个答案:

答案 0 :(得分:4)

许多性能问题依赖于数据库引擎。本文的其余部分将涉及MySQL。

IN()子句在索引字段上可能有不良性能,但在您给出的示例中不会。最多一定数量的user_id,您的查询将是最快的。但是,在某些时候,将user_ids放入临时表并加入其中会变得更快。您可以在MySQL here中查看有关IN()与临时表的性能的更多详细信息。

如果user_ids列表基于用户的某些属性(例如管理员或无效),那么您可以在User表中添加一个字段,并完全避免此问题。

答案 1 :(得分:3)

使用“in”子句的替代方法是“或”id,即“id = 1或id = 2或id = 3”。如果只有少数你可能会以这种方式获得一些速度。

来自文档:http://www.sqlalchemy.org/docs/ormtutorial.html#common-filter-operators

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

您没有说出您正在使用的DBM,但您的管理员可能是您最好的资产。了解要使用的构造的最佳方法是分析查询并尝试几个不同的构造,以便了解特定数据库引擎处理各种查询的情况。无论你使用什么数据库,如果它支持“或”或“in”,你可能会使用它们获得很大的速度,而不是循环遍历你需要的所有id并进行单独的查询。

可能会发现,与更改代码的其他部分相比,担心是否使用“in”或其他构造并不会对应用程序的整体速度产生很大影响。数据库引擎在优化简单查询方面非常狡猾,只要您的查询合理,您就可以获得良好的性能。我们必须学习编程的一个方面是首先使代码运行良好,然后在出现问题时进行测试和优化。通常我们假设我们知道瓶颈在哪里但是分析工具会显示我们错了。使用分析器和基准测试工具可以帮助缩小问题范围,并显示加速任何需要调整的最佳方法。

答案 2 :(得分:0)

@Hadrien(OP)使用过:

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()