我正在使用带有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()
似乎可以解决问题,并加快速度。我仍然感到困惑,为什么初始查询速度较慢。
答案 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')