2013-01-08 118 views
3

我已經在我的應用程序中向mysql的​​函數發出緩慢的聲音。我製作了一個簡單的sql查詢來解釋這個問題:python mysql execute()很慢

SELECT * FROM `cid444_agg_big` c WHERE 1 

>>> import MySQLdb as mdb 
>>> import time; 
>>> 
>>> dbconn = mdb.connect('localhost','*****','*****','*****'); 
>>> cursorconn = dbconn.cursor() 
>>> 
>>> sql="SELECT * FROM `cid444_agg_big` c WHERE 1"; 
>>> 
>>> startstart=time.time(); 
>>> cursorconn.execute(sql); 
21600L #returned 21600 records 
>>> print time.time()-startstart, "for execute()" 
2.86254501343 for execute() #why does this take so long? 
>>> 
>>> startstart=time.time(); 
>>> rows = cursorconn.fetchall() 
>>> print time.time()-startstart, "for fetchall()" 
0.0021288394928 for fetchall() #this is very fast, no problem with fetchall() 

在mysql shell中運行此查詢會產生0.27秒或10倍的更快!

我唯一的想法就是返回數據的大小。這將返回21600「寬」行。所以這是很多數據被髮送到Python。數據庫是localhost,所以沒有網絡延遲。

爲什麼這需要這麼長時間?

更新的詳細信息

我寫在PHP一個類似的腳本:

$c = mysql_connect ('localhost', '*****', '****', true); 
mysql_select_db ('cachedata', $c); 

$time_start = microtime_float(); 
$sql="SELECT * FROM `cid444_agg_big` c WHERE 1"; 
$q=mysql_query($sql);$c=0; 
while($r=mysql_fetch_array($q)) 
$c++;//do something? 
echo "Did ".$c." loops in ".(microtime_float() - $time_start)." seconds\n"; 


function microtime_float(){//function taken from php.net 
    list($usec, $sec) = explode(" ", microtime()); 
    return ((float)$usec + (float)$sec); 
} 

此打印:

Did 21600 loops in 0.56120800971985 seconds 

這個循環上的所有數據,而不是在獲取所有的一旦。 PHP似乎比Python版本快6倍 ....

回答

2

The default MySQLdb cursor獲取完整的結果集在客戶端上execute,並且fetchall()將不僅僅是數據從內存中拷貝到內存中。

如果要將結果集存儲在服務器上並按需獲取,則應該使用SSCursor來代替。

Cursor:
這 是標準類光標返回行作爲元組並將結果保存在客戶端設置。

SSCursor:
這是一個Cursor類返回行的元組,並將結果存儲在服務器中設定。

+0

我正在循環使用所有這些數據。我是否正確地認爲在我的情況下運行'execute()'並獲取所有內容大致等價於使用'SSCursor'的方法,並假設我需要所有這些記錄並根據需要提取記錄? 'SSCursor'會在時間上獲得實質性收益嗎? – Landon

+0

@Landon如果你正在提取所有數據,我會假設'Cursor'更快,因爲它可以傳輸所有數據而不考慮任何訪問模式。 'SSCursor'主要適用於不一定使用所有數據的查詢,或者用於大型結果集來節省內存。 –

+0

值得注意的是,使用SSCursor,你不能打開一個到數據庫的新連接,或者直到關閉當前的遊標才執行一個新的查詢。 –