[英]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.