现在的位置: 首页Mysql>正文
合并MyISAM文件
2012年11月27日 Mysql 暂无评论 ⁄ 被围观 4,743 view+

Recently, I found myself involved in the migration of a large read-only InnoDB database to MyISAM (eventually packed). The only issue was that for one of the table, we were talking of 5 TB of data, 23B rows. Not small… I calculated that with something like insert into MyISAM_table… select * from Innodb_table… would take about 10 days. The bottleneck was clearly the lack of concurrency on the read part from InnoDB and then the key management for MyISAM. The server has many dozen drives so it was easy to add more concurrency so I kicked off, from a script, insertions into 16 identical MyISAM files for distinct parts of the table. That was much faster and would complete within a day.

Then, while the Innodb extraction was running at a nice pace, I thought about the next phase. My first idea was simply to do insert into MyISAM_table select * from MyISAM_table1 and so on for the 16 files. Since MyISAM are flat files, that should be faster, especially with the keys disabled. At that point, I remembered, from a previous disaster recovery work where a database directory has been wiped out that the MyISAM files have no headers which make them difficult (read almost impossible) to locate on a drive with tools like ext3grep. No headers… that means the first byte of byte of a file is the first byte of the first row… So we should be able to concatenate these files. Let’s see.

mysql> create table test_concat(id int unsigned not null, primary key (id)) engine=myisam;
Query OK, 0 rows affected (0.01 sec)

mysql> create table test_concat_part like test_concat;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into test_concat (id) value (1),(2),(3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into test_concat_part (id) value (4),(5),(6);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> flush tables;
Query OK, 0 rows affected (0.01 sec)

Then, at the shell command line:

root@django:/var/lib/mysql/test# ls
test_concat.frm  test_concat.MYD  test_concat.MYI  test_concat_part.frm  test_concat_part.MYD  test_concat_part.MYI
root@django:/var/lib/mysql/test#
root@django:/var/lib/mysql/test# cat test_concat_part.MYD >> test_concat.MYD
root@django:/var/lib/mysql/test# myisamchk -rq test_concat
- check record delete-chain
- recovering (with sort) MyISAM-table 'test_concat'
Data records: 3
- Fixing index 1
Data records: 6

And then, back in mysql:

mysql> use test
Database changed
mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from test_concat;
+----+
| id |
+----+
|  1 |
|  2 |
|  3 |
|  4 |
|  5 |
|  6 |
+----+
6 rows in set (0.00 sec)

So, yes, you can concatenate MyISAM files, even when multiple keys are defined. Not for everyday use but still pretty cool.

Addendum

Following Peter’s comment, I added varchar and deleted rows to the mix:

mysql> truncate table test_concat;
Query OK, 0 rows affected (0.00 sec)

mysql> truncate table test_concat_part;
Query OK, 0 rows affected (0.01 sec)

mysql> alter table test_concat add data varchar(10);
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table test_concat_part add data varchar(10);
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> insert into test_concat (id,data) value (1,'one'),(2,'two'),(3,'three');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> insert into test_concat_part (id,data) value (44,'todelete'),(4,'four'),(5,'five'),(6,'six');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> delete from test_concat_part where id = 44;
Query OK, 1 row affected (0.00 sec)

mysql> flush tables;
Query OK, 0 rows affected (0.00 sec)

root@django:/var/lib/mysql/test# myisamchk -rq test_concat
- check record delete-chain
- recovering (with sort) MyISAM-table 'test_concat'
Data records: 3
- Fixing index 1
myisamchk: error: Couldn't fix table with quick recovery: Found wrong number of deleted records
myisamchk: error: Run recovery again without -q
MyISAM-table 'test_concat' is not fixed because of errors
Try fixing it by using the --safe-recover (-o), the --force (-f) option or by not using the --quick (-q) flag
root@django:/var/lib/mysql/test# myisamchk -r test_concat
- recovering (with sort) MyISAM-table 'test_concat'
Data records: 6
- Fixing index 1

mysql> select * from test_concat;
+----+-------+
| id | data  |
+----+-------+
|  1 | one   |
|  2 | two   |
|  3 | three |
|  4 | four  |
|  5 | five  |
|  6 | six   |
+----+-------+
6 rows in set (0.00 sec)

So varchar columns are supported without any issue but, deleted rows prevent the use of the quick option for myisamchk.

来源:http://www.mysqlperformanceblog.com/2012/11/19/concatenating-myisam-files/

给我留言

留言无头像?


×
腾讯微博