2013-02-07 89 views
27

我正在使用MySQL數據庫SQLAlchemy,我想計算表中的行(大約300k)。 SQLAlchemy count函數的運行時間約爲直接在MySQL中編寫相同查詢的50倍。難道我做錯了什麼?爲什麼SQLAlchemy count()比原始查詢慢得多?

# 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

我不知道SQLAlchemy的事情,但它聽起來好像它會迭代結果而不是發送一個計數(*)到後端。 –

+0

[docs](http://docs.sqlalchemy.org/ru/latest/orm/query.html#sqlalchemy.orm.query.Query.count)似乎表示,count函數只是發出一個count語句。 – mtth

+1

當您創建'engine'時,使用'echo = True'參數啓用日誌記錄,以查看實際生成的SQL語句。 – van

回答

42

不幸的是,MySQL對子查詢有着可怕的,可怕的支持,這對我們的影響非常消極。該SQLAlchemy docs指出,「優化」查詢可以使用query(func.count(Segment.id))實現:

Return a count of rows this Query would return.

This generates the SQL for this Query as follows:

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

For fine grained control over specific columns to count, to skip the usage of a subquery or otherwise control of the FROM clause, or to use other aggregate functions, use func expressions in conjunction with query(), i.e.:

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))) 
+0

感謝您的回覆。你能否詳細說明MySQL的「對子查詢的嚴重支持」? – mtth

+0

最好的解釋是通過谷歌不幸這是最可怕的格式化的博客文章,但得到了這個想法:http://www.mysqlperformanceblog.com/2010/10/25/mysql-limitations-part-3-subqueries/ – zzzeek

+0

較長的職位,但接近尾聲更詳細地介紹了MySQL在這方面的計劃:http://www.xaprb。com/blog/2006/04/30/how-to-optimize-subqueries-and-join-in-mysql/ – zzzeek

2

我花了很長時間才找到這爲解決我的問題。我收到以下錯誤:

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

這樣::

sqlalchemy.exc.DatabaseError: (mysql.connector.errors.DatabaseError) 126 (HY000): Incorrect key file for table '/tmp/#sql_40ab_0.MYI'; try to repair it

當我改變了這個問題得到解決

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

的原因是SQLAlchemy的的計數()計數子查詢的結果仍然在完成大量的工作來檢索您正在計算的行。這種行爲是不可知的底層數據庫;這不是MySQL的問題。

SQLAlchemy docs解釋如何通過從sqlalchemy導入func來發出沒有​​子查詢的計數。

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

>>>SELECT count(users.id) AS count_1 \nFROM users') 
相關問題