MySQL在排序期间耗尽了1.5TB的磁盘空间

时间:2010-10-11 17:32:19

标签: mysql

我有一张包含大约14亿条记录的表格,格式如下:

mysql> describe _2009all;
+---------------+--------------+------+-----+---------+-------+
| Field         | Type         | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+-------+
| userId        | int(11)      | YES  | MUL | NULL    |       |
| type          | varchar(50)  | YES  |     | NULL    |       |
| kind          | varchar(50)  | YES  |     | NULL    |       |
| description   | varchar(255) | YES  |     | NULL    |       |
| bundleVersion | varchar(255) | YES  |     | NULL    |       |
| bundleId      | varchar(255) | YES  |     | NULL    |       |
| time          | bigint(20)   | YES  |     | NULL    |       |
+---------------+--------------+------+-----+---------+-------+
7 rows in set (0.02 sec)

整个数据库占用的容量不到0.4TB,我有大约1.5TB的可用磁盘空间。

我正在尝试准备用于分析的数据,其中我会查看每个用户随着时间的推移所做的事情。所以我运行以下声明:

create table sorted2009 AS (select * from _2009all order by userid,time);

该声明(显然)需要很长时间才能运行,但在某些时候,它耗尽了所有可用磁盘空间,并且出现“错误3(HY000):错误写入文件”错误。

关于如何创建排序表的任何想法?提前谢谢。

澄清

Martin:只有一个分区。

Andy:我试图解决的问题是“select * from _2009all order by userid,time”的结果是我将在接下来的几个月内进行大量检查的结果。因此,我不是每次想要检查结果时运行此查询,而是希望将结果放在表中以便更快地访问。

我最初认为随着时间的推移索引会浪费空间,因为时间戳大多是唯一的。但我只是在_2009all中添加了一个时间字段的索引,索引占用了合理的空间。但现在要对两个索引进行排序(我认为你的意思是“索引行走”):

mysql> select * from _2009all order by userId,time limit 2;
...
2 rows in set (25 min 36.48 sec)

是的,我说25分钟太长了。但是,如果你的建议意味着别的东西,我会接受其他选择。

bot43:

将索引添加到时间字段后:

mysql> explain select * from _2009all order by userid,time;
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows       | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
|  1 | SIMPLE      | _2009all | ALL  | NULL          | NULL | NULL    | NULL | 1384378798 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
1 row in set (0.05 sec)

mysql> explain select userId,type,kind,description,bundleVersion,bundleId,time from _2009all order by userid,time
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows       | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
|  1 | SIMPLE      | _2009all | ALL  | NULL          | NULL | NULL    | NULL | 1384378798 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------------+----------------+
1 row in set (0.00 sec)

关于DBMS存储表的任何该死的感觉都很好。我想我需要另一种解决方案。

2 个答案:

答案 0 :(得分:2)

你在桌上有什么索引?

你不能在两个柱子上加composite index吗?

ALTER TABLE `_2009all` ADD INDEX ( `userId` , `time` ) ;

答案 1 :(得分:0)

我不认为你可以使用一些技巧来使这个操作占用更少的空间。如果那就是你要问的。简短而简单的答案是:通过添加另一个硬盘来获得更多空间。有了这种DB,无论如何你都需要它。

您还可以尝试将表拆分为两个或多个部分,并一次排序和查看每个表。如果这对你有用。 GL!