繁体   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