我需要将一些非常大的MySQL表转储到csv(托管在RDS上,所以没有SELECT INTO OUTFILE)。这些表远远大于其服务器上的可用内存。
如果我使用带有SELECT * FROM a_big_table
或fetchmany()
的python框架执行fetchone()
来获取记录,则MySQL 5.6
会尝试首先将整个表读入内存(我预计将导致缓存到磁盘),还是比这更聪明?
编辑:为澄清起见,我的意思是将整个结果集存储在MySQL缓存中(而不是Python!)。
第二次编辑:在第一次编辑中将“排序”错字更改为“存储”。关于此案的评论仍然有用!
答案 0 :(得分:3)
服务器上已使用的内存量由缓冲池大小配置设置定义。几乎无需担心服务器端发生了什么。您的提取应用程序可能会成为瓶颈,因此写入转储的速度可能比MySQL输出的速度慢。服务器在获取数据时只负责填充缓冲区。从服务器的角度来看,获取一个较大的结果集比进行多个较小范围的查询更有效,对资源的需求也更少...
答案 1 :(得分:2)
通常在应用程序级别的数据库调用中,不返回整个结果集,而是返回指向结果集的游标。然后取决于应用程序语言(例如Python)来迭代该结果集并检索记录。
用于MySQL的Python连接器的documentation确认了这一点:
默认情况下,MySQL Connector / Python不会缓冲或预取结果。这意味着在执行查询后,您的程序将负责获取数据(重点是我的)。当查询返回大结果集时,这避免了过多的内存使用。如果您知道结果集足够小以至于可以一次处理所有内容,则可以通过将buffered设置为True来立即获取结果。也可以为每个游标设置此设置(请参见第10.2.6节“ MySQLConnection.cursor()方法”)。
在客户端程序获取查询结果之前,通常不会读取查询生成的结果。要自动使用和丢弃结果集,请将consume_results选项设置为True。结果是读取了所有结果,这对于大型结果集可能很慢。 (在这种情况下,最好关闭并重新打开连接。)
因此,从内存需求的角度来看,使用SELECT *
查询,然后一次写入一个记录或一次写入记录组的策略应该可行。您的Python代码应该只需要尽可能多的内存来保存您要写入文件的当前记录。