pla*_*etp 9 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
}
Run Code Online (Sandbox Code Playgroud)
逐行检索结果集,而不将其加载到RAM.但我在DBI或MySQL文档中找不到任何引用.结果集是如何真正创建和检索的?它对简单的选择和连接是否有效?
这不是真的(如果我们谈论的是数据库服务器本身,而不是客户端层).
MySQL可以缓冲整个结果集,但这不一定完成,如果完成,不一定在RAM.
如果使用内联视图(SELECT FROM (SELECT …)),查询需要排序(显示为using filesort),或者计划需要创建临时表(using temporary在查询计划中显示),则结果集将被缓冲.
即使using temporary,MySQL只有当表的大小不超过设置的限制时,才将表保留在内存中tmp_table.当表超过此限制时,它将转换memory为MyISAM存储在磁盘上并存储在磁盘上.
但是,您可以MySQL通过SQL_BUFFER_RESULT向最外层附加指令来明确指示缓冲结果集SELECT.
有关更多详细信息,请参阅文档.
小智 6
你的同事是对的.
默认情况下,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 .