如何在MySQL中为大表创建索引且不生成磁盘临时文件
如何在MyISAM大表上不生成临时文件创建索引(允许锁表)
嘿,这个问题问得很实在!既然你不介意表被锁定,那针对你说的这种用.MYD/.MYI文件的MyISAM大表,完全可以绕过MySQL默认的全表复制逻辑,直接在原表文件上创建索引,能大幅减少磁盘IO和耗时。下面给你两种可行的方案:
方案1:在线锁表后用ALTER TABLE的INPLACE算法
MyISAM引擎支持在创建二级索引时用ALGORITHM=INPLACE这个参数——它不会复制整个.MYD数据文件,只会直接修改.MYI索引文件。不过因为要直接操作索引文件,表会被加上写锁,期间没法做任何读写操作(刚好符合你不介意锁表的需求)。
执行的SQL命令是这样的:
LOCK TABLES your_table WRITE; ALTER TABLE your_table ADD INDEX idx_your_index(your_column1, your_column2) ALGORITHM=INPLACE; UNLOCK TABLES;
小提示:其实
ALTER TABLE ... ALGORITHM=INPLACE本身会自动加写锁,但显式锁表能避免其他操作中途干扰。另外要注意,这个方法只适用于二级索引,要是你要创建主键索引,还是会复制表——因为主键是MyISAM的聚簇索引,关联着数据文件的存储顺序,没法直接修改。
方案2:离线用myisamchk工具创建索引
如果你能接受表暂时完全离线(没法被访问),那用myisamchk工具是效率最高的选择——它直接操作磁盘上的.MYI和.MYD文件,完全不会生成任何临时复制文件。
步骤大概是这样:
先把表锁定或者停掉MySQL服务:
要是不想停服务,就先执行这条SQL锁表:FLUSH TABLES your_table WITH READ LOCK;(如果直接停MySQL服务,这一步可以跳过)
找到你的表文件存在哪(一般在MySQL的数据目录里,对应你数据库名的文件夹),然后用命令行执行myisamchk:
要是想重建所有索引(包括你要加的新索引),可以这么写:myisamchk --keys-used=0 --write your_table.MYI myisamchk --recover --quick --sort-index your_table.MYI简单解释下:
--keys-used=0先禁用所有现有索引,避免重建时出问题--recover --quick快速重建索引,--sort-index会把索引树排序,能提升后续的查询性能
如果你只想单独加某个新索引,需要先了解表的索引位掩码,然后用--add-index参数,不过直接重建所有索引对大表来说反而更省心。
操作完之后,解锁表或者重启MySQL服务就行:
UNLOCK TABLES;
一些必须注意的点
- 这俩方案都只适用于MyISAM引擎哦!你提到了.MYD/.MYI,所以肯定没问题,但要是换成InnoDB,逻辑就完全不一样了。
- 操作前一定要备份表文件!大表操作风险不小,备份能帮你兜底,避免意外搞砸数据。
- 方案1的
ALGORITHM=INPLACE是MySQL 5.6及以上版本才支持的,要是你用的是更老的版本,那直接用方案2更稳妥。
内容的提问来源于stack exchange,提问作者Tom Shir
相关产品推荐
相关产品推荐

