我有一个包含几十亿行数据的表,我正在尝试一次构建5个索引。表格格式为MyISAM以节省空间。一旦我构建索引,这将是一个静态表,我只需要它是只读的。
我使用此命令创建了索引:
alter table links8添加索引(uid,tid),添加索引(日期),添加索引(tid),添加索引(userid),添加索引(更新,uid,tid,userid,日期);
该命令已运行超过45天。你看对了:45天。我可以看到临时文件仍然被访问,它不是一个死的查询。
我的问题是:wtf?似乎最多需要花费几个小时来排序和构建索引,即使行数为几十亿。
由于我有一个静态表,是否有另一个有意义的存储引擎? Innodb占用太多空间。
答案 0 :(得分:0)
现在,你是绝对正确的,在内存中排序数十亿的价值不应该花费很长时间。对(updated,uid,tid,userid,date)
中连接值的几十亿个值进行排序,尽管很可能不会在RAM中发生。假设updated
和date
属于datetime
类型,它们各占8个字节; uid
,tid
,userid
通常为32位整数,但由于您的表格有> 2 ** 32个条目(I' m假设),唯一ID也是8个字节长。因此,类型(updated,uid,tid,userid,date)
的一个值将是40B长。
现在让我们说50亿这些;您将获得200 GB的纯行数据,您需要对其进行排序以构建索引。假设你没有在某台大型计算机上执行此操作,显然需要将这些值的一部分交换到磁盘 - 因为你看到临时文件出现了,我猜测这种情况正在发生,并且MySQL正在积极地这样做本身。现在,迭代地处理部分行的排序算法要慢得多,因为首先对所有部分进行排序,然后以比以前更好的排序方式混合部分,而不是重新划分数据,你可以对零件进行分类......在磁盘之间存储和加载。
顺便说一下,如果不采取纠正措施,那么45天的持续内存操作很可能容易出现内存位错误(基本上,这种任务使用ECC,或者你最终得到索引的,损坏的数据)
MySQL自己suggest你只是建立一个特殊的MD5索引,它接受你的搜索元组的哈希并查找它,因为排序128位(== 16字节)MD5哈希可能比排序5 * 8Byte更容易== 40 * 8位== 320位长复合行。
答案 1 :(得分:0)
我找到了更好的解决方案。
我创建了一个新表,其中已有索引,然后从一个表向另一个表发出插入。它的工作方式是填充MYD(原始数据文件),然后在此之后创建索引。一旦它开始创建索引,我就终止了查询。然后在文件系统上我使用myisamchk手动修复表。
该命令看起来像这样:
myisamchk --force --fast --update-state --key_buffer_size = 2000M --sort_buffer_size = 2000M --read_buffer_size = 10M --write_buffer_size = 10M TABLE.MYI
整个过程花了不到12个小时,数据看起来不错!
更新:
以下是汇总的流程。
使用索引创建table2与table1的缩进;
插入table2 select * from table1;
一旦MYD文件已满,它就会从MYI文件开始终止查询
然后关闭mysql并运行myisamchk查询并重启mysql
OR
将table2.MYD和table2.MYI复制到table3.MYD和table3.MYI,然后运行myisamchk,然后将table2.frm复制到table3.frm并更改权限,当它完成后你应该能够访问table3而不重启mysql