簡體   English   中英

執行語句是否總是占用結果集的內存?

[英]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 temporaryMySQL只在其大小不超過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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM