为什么SQLAlchemy count()比原始查询慢得多?

时间:2013-02-07 15:37:56

标签: mysql sqlalchemy

我正在使用带有MySQL数据库的SQLAlchemy,我想计算表中的行数(大约300k)。 SQLAlchemy count函数的运行时间大约是在MySQL中直接编写相同查询的50倍。我做错了吗?

# this takes over 3 seconds to return
session.query(Segment).count()

然而:

SELECT COUNT(*) FROM segments;
+----------+
| COUNT(*) |
+----------+
|   281992 |
+----------+
1 row in set (0.07 sec)

速度的差异随着桌子的大小而增加(在100k行以下几乎不可察觉)。

更新

使用session.query(Segment.id).count()代替session.query(Segment).count()似乎可以解决问题,并加快速度。我仍然感到困惑,为什么初始查询速度较慢。

3 个答案:

答案 0 :(得分:54)

不幸的是,MySQL对子查询的支持非常可怕,这对我们的影响很大。 SQLAlchemy docs指出"优化"可以使用query(func.count(Segment.id))

来实现查询
  

返回此Query将返回的行数。

     

这将为此Query生成SQL,如下所示:

SELECT count(1) AS count_1 FROM (
     SELECT <rest of query follows...> ) AS anon_1
     

要对要计数的特定列进行细粒度控制,请跳过   使用子查询或以其他方式控制FROM子句,或使用   其他聚合函数,结合使用func表达式   query(),即:

     
from sqlalchemy import func

# count User records, without
# using a subquery.
session.query(func.count(User.id))

# return count of user "id" grouped
# by "name"
session.query(func.count(User.id)).\
        group_by(User.name)

from sqlalchemy import distinct

# count distinct "name" values
session.query(func.count(distinct(User.name)))

答案 1 :(得分:5)

我花了很长时间才发现这是我问题的解决方案。我收到以下错误:

  

sqlalchemy.exc.DatabaseError:(mysql.connector.errors.DatabaseError)   126(HY000):表'/tmp/#sql_40ab_0.MYI'的密钥文件不正确;尝试   修理它

我改变了这个问题后解决了问题:

query = session.query(rumorClass).filter(rumorClass.exchangeDataState == state)
return query.count()

到此:

query = session.query(func.count(rumorClass.id)).filter(rumorClass.exchangeDataState == state)
return query.scalar()

答案 2 :(得分:3)

原因是SQLAlchemy的count()正在计算子查询的结果,该子查询仍在执行全部工作以检索您正在计算的行。此行为与底层数据库无关;这不是MySQL的问题。

SQLAlchemy docs通过从func导入sqlalchemy来解释如何在没有子查询的情况下发出计数。

session.query(func.count(User.id)).scalar()

>>>SELECT count(users.id) AS count_1 \nFROM users')