您好,登錄后才能下訂單哦!
這篇文章主要講解了“分析PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸的原因”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“分析PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸的原因”吧!
當Python 有讀寫 MySQL 數(shù)據(jù)的需求時,我們經(jīng)常使用PyMySQL這個第三方庫來完成。
有時候如果一張表里面的數(shù)據(jù)非常大,但是我們只需要讀取一條數(shù)據(jù),此時我們可能會想當然地使用cursor.fetchone()這個方法,以為這樣就真的可以只讀取一條數(shù)據(jù):
import pymysql connection = pymysql.connect(host='localhost', user='user', password='passwd', db='db', charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor) with connection.cursor() as cursor: db = 'select * from users where age > 10' cursor.execute(db) one_user = cursor.fetchone()
但實際上,上面這段代碼,與下面這段代碼沒有任何區(qū)別:
... with connection.cursor() as cursor: sql = 'select * from users where age > 10' cursor.execute(sql) all_users = cursor.fetchall() 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行調(diào)用了self._query方法。我們再去到這個方法里面:
看到代碼第322行,調(diào)用了self._do_get_result()方法。我們再去這個方法里面看看:
注意代碼第342行,此時已經(jīng)把所有數(shù)據(jù)存放到了self._rows列表中。
現(xiàn)在我們來看cursor.fetchone()方法:
可以看到,這里不過是從列表里面根據(jù)下標讀取一條數(shù)據(jù)出來而已。
再看cursor.fetchall()方法:
如果之前先多次調(diào)用過cursor.fetchone(),那么self.rownumber會持續(xù)增加。而調(diào)用cursor.fetchall()時,跳過之前已經(jīng)返回過的數(shù)據(jù),直接返回剩下的全部數(shù)據(jù)即可。如果之前沒有調(diào)用過cursor.fetchone(),那么直接返回全部數(shù)據(jù)。
所以,單純使用cursor.fetchone()并不能節(jié)省內(nèi)存,如果表里面的數(shù)據(jù)非常大,還是會有內(nèi)存爆炸的危險。
那么真正的解決辦法是什么呢?真正的解決辦法在創(chuàng)建數(shù)據(jù)庫連接的時候指定游標類型。pymysql.connect有一個參數(shù)叫做cursorclass,把它的值設(shè)定為pymysql.SSDictCursor即可解決問題。
我們來看一下如何正確使用它:
import pymysql connection = pymysql.connect(host='localhost', user='user', password='passwd', db='db', charset='utf8mb4', cursorclass=pymysql.cursors.SSDictCursor) with connection.cursor() as cursor: db = 'select * from users where age > 10' cursor.execute(db) for row in cursor: print('對 cursor 直接進行迭代,每循環(huán)一次,從數(shù)據(jù)庫讀取一條數(shù)據(jù)。不會提前把所有數(shù)據(jù)讀取到內(nèi)存中。') print(row['name'])
感謝各位的閱讀,以上就是“分析PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸的原因”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對分析PyMySQL獲取一條數(shù)據(jù)會讓內(nèi)存爆炸的原因這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。