[英]Does MySQL (5.6) always cache the entire result set for a query in memory/on disk?
[英]Does executing a statement always take in memory for the result set?
一位同事告訴我,執行SQL語句總是將數據放入RAM / swap由數據庫服務器。 因此,選擇大的結果集是不實際的。
我以為這樣的代碼
my $sth = $dbh->prepare('SELECT million_rows FROM table');
while (my @data = $sth->fetchrow) {
# process the row
}
逐行檢索結果集,而不將其加載到RAM。 但我在DBI或MySQL文檔中找不到任何引用。 結果集是如何真正創建和檢索的? 它對簡單的選擇和連接是否有效?
這不是真的(如果我們談論的是數據庫服務器本身,而不是客戶端層)。
MySQL
可以緩沖整個結果集,但這不一定完成,如果完成,不一定在RAM
。
如果您使用內聯視圖( SELECT FROM (SELECT …)
),查詢需要排序(顯示為using filesort
),或者計划需要創建臨時表(在using temporary
表時顯示為臨時表),結果集將被緩沖查詢計划)。
即使using temporary
, MySQL
只在其大小不超過tmp_table
設置的限制時將表保留在內存中。 當表超過此限制時,它將從memory
轉換為MyISAM
並存儲在磁盤上。
但是,您可以通過將SQL_BUFFER_RESULT
指令附加到最外面的SELECT
來明確指示MySQL
緩沖結果集。
有關更多詳細信息,請參閱文檔 。
你的同事是對的。
默認情況下,perl模塊DBD :: mysql使用mysql_store_result,它確實讀取所有SELECT數據並將其緩存在RAM中。 除非您更改該默認值,否則當您在DBI中逐行獲取時,它只是從內存緩沖區中讀取它們。
這通常是您想要的,除非您有非常大的結果集。 否則,在從mysqld獲取最后一個數據之前,它必須保持該數據准備就緒,我的理解是它會導致寫入相同行的塊(塊?表?)。
請記住,現代機器有很多RAM。 百萬行結果集通常不是什么大問題。 即使每行大小為1 KB,也只有1 GB RAM加上開銷。
如果您要處理數百萬行BLOB,也許您確實需要mysql_use_result - 或者您希望以漸進使用LIMIT x,y
方式選擇這些行。
有關詳細信息,請參閱perldoc DBD::mysql
mysql_use_result和mysql_store_result。
不,這不是它的工作原理。
數據庫不會在RAM / swap中保存行。
但是,它會嘗試,並且mysql在這里努力嘗試,盡可能地緩存(索引,結果等...)。 您的mysql配置為不同類型的緩存(針對不同類型的存儲引擎)提供可用內存緩沖區的值 - 您不應允許此緩存交換。
測試一下
底線 - 應該很容易使用客戶端來測試它(我不知道perl的dbi,它可能,但我懷疑它,正在做一些迫使mysql加載准備的東西)。 無論如何......測試一下:
如果您實際上在SELECT SQL_NO_CACHE million_rows FROM table
上發布了一個prepare,那么只獲取數百萬行中的幾行。 然后,您應該將性能與SELECT SQL_NO_CACHE only_fetched_rows FROM table
進行比較,並查看該票價的情況。 如果表現具有可比性(和快速),那么我相信你可以打電話給你同事的虛張聲勢。
此外,如果你啟用實際發給mysql的語句的日志並給我們一個轉錄本,那么我們(非perl人)可以給出更多關於mysql做什么的明確答案。
我對此並不是很熟悉,但它看起來像DBD :: mysql可以根據mysql_use_result屬性預先獲取所有內容或僅根據需要獲取所有內容。 請參閱DBD :: mysql和MySQL文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.