排序非常大的mysql表并写入文件

时间:2013-12-29 14:01:28

标签: mysql

我有一个非常大的表,我正在尝试使用查询对文件进行排序和写入:

 select * from t1 order by user_id,tstamp into outfile 'sample.tsv';

该表非常大(大约600-7亿行)并且在磁盘上使用~180GB,并且尝试运行查询会给我“设备上没有剩余空间”错误,显然写了这么多数据tmp目录,它正在最大化硬盘并打破查询。

我已经最大化了包含tmp文件夹的驱动器上的可用空间(接近1TB免费!)但查询仍然失败并出现相同的错误,所以我需要一个解决方案,而不是在tmp目录中创建更多空间。

到目前为止,我想到的一个想法是迭代地分解排序,利用这样的事实:对于56000左右的用户ID中的每一个,平均只有10-20,000条记录。使用一些伪代码,我想这看起来像这样:

for each unique uid:
    select * from t1 where user_id=uid order by tstamp
    append result to file

我认为这会起作用(使用Python MySQL包装器或类似方法)但是有一个更简单,纯粹的MySQL解决方案吗?

1 个答案:

答案 0 :(得分:1)

评论太长了。

我不确定是否有比用户ID提取方法更好的方法。您可能想要使用更大的块。只要数据适合内存,排序应该是合理的。

虽然对所有数据进行排序可能不可行,但您可以在user_id上创建索引。这样的索引会加快您的查询速度。如果没有索引,每次迭代都需要进行全表扫描。

user_id, tstamp上构建索引可能会帮助查询(即使可能)。问题是数据不适合内存。即使你有这样的索引,当你去使用它时,你最终会遇到一种叫做“颠簸”的情况。查询将开始读取索引。每条记录都在一个单独的页面上(近似)。很快,页面缓存就会填满内存。然后引擎查看索引中的下一条记录。它几乎肯定不在页面缓存中,因此它必须从磁盘读取页面。这种情况还在继续每个记录读取都需要额外命中磁盘。

此问题的解决方案是合并排序算法。在某些情况下,在数据库外部进行排序更为可行。但180 GB的文件仍然很大。