57

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()と、トリックが実行され、速度が上がるようです。しかし、なぜ最初のクエリが遅いのか、私はまだ戸惑っています。

4

3 に答える 3

85

残念ながら、MySQLはサブクエリのひどい、ひどいサポートを持っており、これは非常に悪い方法で私たちに影響を与えています。SQLAlchemyのドキュメントでは、「最適化された」クエリは次を使用して実現できると指摘されていますquery(func.count(Segment.id))

このクエリが返す行数を返します。

これにより、このクエリのSQLが次のように生成されます。

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

カウントする特定の列をきめ細かく制御するには、サブクエリの使用をスキップするか、FROM句の制御をスキップするか、他の集計関数を使用するには、query()と組み合わせてfunc式を使用します。

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)))
于 2013-02-07T18:23:14.760 に答える
14

その理由は、SQLAlchemyのcount()が、カウントしている行を取得するためにまだ全量の作業を行っているサブクエリの結果をカウントしているためです。この動作は、基盤となるデータベースに依存しません。MySQLの問題ではありません。

SQLAlchemyのドキュメントfuncでは、からインポートすることにより、サブクエリなしでカウントを発行する方法を説明していsqlalchemyます。

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

>>>SELECT count(users.id) AS count_1 \nFROM users')
于 2017-12-13T20:38:15.010 に答える
7

これが私の問題の解決策であると見つけるのに長い時間がかかりました。次のエラーが発生していました。

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()
于 2016-03-18T18:47:58.370 に答える