Mysql 执行语句是否总是占用结果集的内存?

Mysql 执行语句是否总是占用结果集的内存?,mysql,perl,resources,prepared-statement,dbi,Mysql,Perl,Resources,Prepared Statement,Dbi,一位同事告诉我,执行SQL语句时,数据库服务器总是将数据放入RAM/swap中。因此,选择大型结果集是不实际的 我认为这样的代码 my $sth = $dbh->prepare('SELECT million_rows FROM table'); while (my @data = $sth->fetchrow) { # process the row } 逐行检索结果集,而不将其加载到RAM。 但我在DBI或MySQL文档中找不到对此的任何引用。结果集是如何创建和检索的?

一位同事告诉我,执行SQL语句时,数据库服务器总是将数据放入RAM/swap中。因此,选择大型结果集是不实际的

我认为这样的代码

my $sth = $dbh->prepare('SELECT million_rows FROM table');
while (my @data = $sth->fetchrow) {
    # process the row
}
逐行检索结果集,而不将其加载到RAM。
但我在DBI或MySQL文档中找不到对此的任何引用。结果集是如何创建和检索的?对于简单的选择和连接是否也一样?

我不太熟悉这一点,但在我看来,DBD::mysql既可以提前获取所有内容,也可以根据mysql\u use\u result属性仅根据需要获取所有内容。请参阅DBD::mysql和mysql文档。

如果我们谈论的是数据库服务器本身,而不是客户机层,那么这是不正确的

MySQL可以缓冲整个结果集,但这不一定要做,如果做了,也不一定要在RAM中做

如果您使用的是内联视图“从选择中选择…”,查询需要排序(显示为使用文件排序),或者计划需要创建一个临时表(显示为在查询计划中使用临时表),则结果集将被缓冲

即使使用临时,MySQL也只在表的大小不超过tmp_表中设置的限制时才将表保留在内存中。当表增长超过此限制时,它将从内存转换为MyISAM并存储在磁盘上

但是,您可以通过将SQL_buffer_RESULT指令附加到最外层的SELECT来显式指示MySQL缓冲结果集


有关更多详细信息,请参阅。

不,它不是这样工作的

数据库不会在RAM/swap中保存行

然而,它会尝试,mysql在这里也会努力尝试,尽可能多地缓存索引、结果等等。。。。您的mysql配置为不同类型的存储引擎的不同类型的缓存提供了可用内存缓冲区的值-您不应该允许交换此缓存

测试一下 一句话——只使用客户端测试应该很容易——我不知道perl的dbi,它可能(但我怀疑)在做一些事情,迫使mysql在prepare上加载所有内容。无论如何测试它:

若您实际上发出了一个prepare on SELECT SQL\u NO\u缓存表中的百万行,然后只提取百万行中的几行。 然后,您应该将性能与SELECT SQL\u NO\u CACHE only\u从表中获取的行进行比较,看看结果如何。 如果表现相当快,那么我相信你可以说你的同事在虚张声势


另外,如果您启用mysql实际发布的语句日志,并给我们一份该语句的副本,那么我们非perl人员可以给出mysql将做什么的更明确的答案。

您的同事是对的

默认情况下,perl模块DBD::mysql使用mysql_store_result,它确实读取所有SELECT数据并将其缓存在RAM中。除非更改默认值,否则当您在DBI中逐行获取数据时,它只是从内存缓冲区中读取数据

这通常是您想要的,除非您有非常大的结果集。否则,在您从mysqld获取最后一个数据之前,它必须保持数据就绪,我的理解是,它会导致写入相同行的块阻塞?桌子

记住,现代机器有很多RAM。百万行的结果集通常不是什么大问题。即使每一行都相当大,只有1KB的内存加上开销

如果要处理数百万行的blob,可能确实需要mysql\u use\u result,或者希望以渐进式使用LIMIT x,y的方式在块中选择这些行


有关详细信息,请参阅perldoc DBD::mysql中的mysql\u use\u result和mysql\u store\u result。

关于目的的问题,为什么需要获取数百万行记录并迭代获取所有记录?mysqldump应该更简单appropriate@ajreal:我需要按插入顺序处理所有行并生成一些报告。好的,这样做合理吗?使用mysql函数生成视图,临时表不足以生成报表?或者甚至考虑将大结果转储到文件中,并打开文件以处理1,不知道DBD::MySQL这样做。然而,你的评论是,除非你有耗尽RAM的危险,否则你不应该在意,这是一个坏建议——一般来说,你应该只获取你需要的数据,如果你不需要数百万行,而且你很少这样做,你不应该获取所有的数据。如果库在应用程序级别而不是在会话级别进行缓存,这种方法会破坏可扩展性。如果库在应用程序级别而不是在会话级别进行缓存,情况会好一些,但仍然不好——如果此缓存经常失效,那么您会在需要更少数据的地方重复获取1GB的数据