日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
為什么PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸

 當Python 有讀寫 MySQL 數(shù)據(jù)的需求時,我們經(jīng)常使用PyMySQL這個第三方庫來完成。

有時候如果一張表里面的數(shù)據(jù)非常大,但是我們只需要讀取一條數(shù)據(jù),此時我們可能會想當然地使用cursor.fetchone()這個方法,以為這樣就真的可以只讀取一條數(shù)據(jù):

 
 
 
 
  1. import pymysql 
  2.  
  3.  
  4. connection = pymysql.connect(host='localhost', 
  5.                              user='user', 
  6.                              password='passwd', 
  7.                              db='db', 
  8.                              charset='utf8mb4', 
  9.                              cursorclass=pymysql.cursors.DictCursor) 
  10.                               
  11. with connection.cursor() as cursor: 
  12.     db = 'select * from users where age > 10' 
  13.     cursor.execute(db) 
  14.     one_user = cursor.fetchone() 

但實際上,上面這段代碼,與下面這段代碼沒有任何區(qū)別:

 
 
 
 
  1. ... 
  2. with connection.cursor() as cursor: 
  3.     sql = 'select * from users where age > 10' 
  4.     cursor.execute(sql) 
  5.     all_users = cursor.fetchall() 
  6.     one_user = all_users[0] 

這是因為,當我們執(zhí)行到cursor.execute(sql)的時候,PyMySQL就已經(jīng)把表里面所有的數(shù)據(jù)讀取到內(nèi)存中了。而后面的cursor.fetchall()或者cursor.fetchone()只不過是從內(nèi)存中返回全部數(shù)據(jù)還是返回1條數(shù)據(jù)而已。

我們來看PyMySQL的源代碼[1]。在cursor.execute()方法代碼如下圖所示:

其中第163行調用了self._query方法。我們再去到這個方法里面:

看到代碼第322行,調用了self._do_get_result()方法。我們再去這個方法里面看看:

注意代碼第342行,此時已經(jīng)把所有數(shù)據(jù)存放到了self._rows列表中。

現(xiàn)在我們來看cursor.fetchone()方法:

可以看到,這里不過是從列表里面根據(jù)下標讀取一條數(shù)據(jù)出來而已。

再看cursor.fetchall()方法:

如果之前先多次調用過cursor.fetchone(),那么self.rownumber會持續(xù)增加。而調用cursor.fetchall()時,跳過之前已經(jīng)返回過的數(shù)據(jù),直接返回剩下的全部數(shù)據(jù)即可。如果之前沒有調用過cursor.fetchone(),那么直接返回全部數(shù)據(jù)。

所以,單純使用cursor.fetchone()并不能節(jié)省內(nèi)存,如果表里面的數(shù)據(jù)非常大,還是會有內(nèi)存爆炸的危險。

那么真正的解決辦法是什么呢?真正的解決辦法在創(chuàng)建數(shù)據(jù)庫連接的時候指定游標類型。pymysql.connect有一個參數(shù)叫做cursorclass,把它的值設定為pymysql.SSDictCursor即可解決問題。

我們來看一下如何正確使用它:

 
 
 
 
  1. import pymysql 
  2.  
  3.  
  4. connection = pymysql.connect(host='localhost', 
  5.                              user='user', 
  6.                              password='passwd', 
  7.                              db='db', 
  8.                              charset='utf8mb4', 
  9.                              cursorclass=pymysql.cursors.SSDictCursor) 
  10.                               
  11. with connection.cursor() as cursor: 
  12.     db = 'select * from users where age > 10' 
  13.     cursor.execute(db) 
  14.     for row in cursor: 
  15.         print('對 cursor 直接進行迭代,每循環(huán)一次,從數(shù)據(jù)庫讀取一條數(shù)據(jù)。不會提前把所有數(shù)據(jù)讀取到內(nèi)存中。') 
  16.         print(row['name']) 

網(wǎng)站欄目:為什么PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸
本文路徑:http://www.5511xx.com/article/cdsppdo.html