"Lost" 分区后 30% 的记录
"Lost" 30% of records after partitioning
我有超过 18GB 数据的 9000 万条记录的 MYISAM table,测试表明它是分区的候选者。
原始架构:
CREATE TABLE `email_tracker` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` varchar(65) COLLATE utf8_unicode_ci NOT NULL,
`userId` int(11) NOT NULL,
`dateSent` datetime NOT NULL,
`dateViewed` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `userId` (`userId`),
KEY `dateSent` (`dateSent`),
KEY `dateViewed` (`dateViewed`),
KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 1 row in set (0.01 sec)
我之前在测试服务器上用 "ALTER TABLE email_tracker PARTITION BY HASH..." 和 运行 典型查询对 table 进行了分区,并且查询没有问题。为了避免在生产数据库上锁定 table,我正在使用这种方法在测试服务器上再次测试,因为我们可以承受在 运行s:
时丢失一些跟踪数据
RENAME TABLE email_tracker TO email_tracker_orig; CREATE TABLE email_tracker LIKE email_tracker_orig;
CREATE TABLE email_tracker_part LIKE email_tracker_orig;
ALTER TABLE email_tracker_part DROP PRIMARY KEY, ADD PRIMARY KEY (id, userId);
ALTER TABLE email_tracker_part PARTITION BY HASH (id + userId) partitions 30;
INSERT INTO email_tracker_part (SELECT * FROM email_tracker_orig);
_orig table 有 90,795,103 条记录。经过查询,_parttable只有68,282,298。我不知道为什么会这样。有什么想法吗?
mysql> select count(*) from email_tracker_orig;
+----------+
| count(*) |
+----------+
| 90795103 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from email_tracker_part;
+----------+
| count(*) |
+----------+
| 68274818 |
+----------+
1 row in set (0.00 sec)
(在后续测试中,_part table 包含的记录数量略有不同,这仍然很奇怪)
编辑 #1:刚刚意识到由于自动增量增量 = 2 用于复制,分区 table 的一半是空的,所以要按 KEY (userId) 重新分区,看看结果如何.
编辑 #2 - 重新分区后仍然相同,因此尝试识别丢失的行以建立模式。
我不确定您的要求,但是 mysql documentation 指出 "the use of hashing expressions involving multiple columns is not particularly recommended." 我建议您只按 id
进行分区。按 id + userId
进行分区不会明显改善元素在分区之间的分布。
看起来 INSERT 查询只是提前终止了——在本例中刚好 40 分钟。只需重新 运行 即可解决丢失记录的问题:
INSERT INTO email_tracker_part (SELECT * FROM email_tracker_orig WHERE id > 148893974);
my.cnf 中没有任何提示超时 40 分钟的内容,我在此测试服务器上 运行 查询的时间比这个长,但我有我的解决方案,所以我会关闭它,即使我仍然不清楚根本原因。
我有超过 18GB 数据的 9000 万条记录的 MYISAM table,测试表明它是分区的候选者。
原始架构:
CREATE TABLE `email_tracker` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`hash` varchar(65) COLLATE utf8_unicode_ci NOT NULL,
`userId` int(11) NOT NULL,
`dateSent` datetime NOT NULL,
`dateViewed` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `userId` (`userId`),
KEY `dateSent` (`dateSent`),
KEY `dateViewed` (`dateViewed`),
KEY `hash` (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci 1 row in set (0.01 sec)
我之前在测试服务器上用 "ALTER TABLE email_tracker PARTITION BY HASH..." 和 运行 典型查询对 table 进行了分区,并且查询没有问题。为了避免在生产数据库上锁定 table,我正在使用这种方法在测试服务器上再次测试,因为我们可以承受在 运行s:
时丢失一些跟踪数据RENAME TABLE email_tracker TO email_tracker_orig; CREATE TABLE email_tracker LIKE email_tracker_orig;
CREATE TABLE email_tracker_part LIKE email_tracker_orig;
ALTER TABLE email_tracker_part DROP PRIMARY KEY, ADD PRIMARY KEY (id, userId);
ALTER TABLE email_tracker_part PARTITION BY HASH (id + userId) partitions 30;
INSERT INTO email_tracker_part (SELECT * FROM email_tracker_orig);
_orig table 有 90,795,103 条记录。经过查询,_parttable只有68,282,298。我不知道为什么会这样。有什么想法吗?
mysql> select count(*) from email_tracker_orig;
+----------+
| count(*) |
+----------+
| 90795103 |
+----------+
1 row in set (0.00 sec)
mysql> select count(*) from email_tracker_part;
+----------+
| count(*) |
+----------+
| 68274818 |
+----------+
1 row in set (0.00 sec)
(在后续测试中,_part table 包含的记录数量略有不同,这仍然很奇怪)
编辑 #1:刚刚意识到由于自动增量增量 = 2 用于复制,分区 table 的一半是空的,所以要按 KEY (userId) 重新分区,看看结果如何.
编辑 #2 - 重新分区后仍然相同,因此尝试识别丢失的行以建立模式。
我不确定您的要求,但是 mysql documentation 指出 "the use of hashing expressions involving multiple columns is not particularly recommended." 我建议您只按 id
进行分区。按 id + userId
进行分区不会明显改善元素在分区之间的分布。
看起来 INSERT 查询只是提前终止了——在本例中刚好 40 分钟。只需重新 运行 即可解决丢失记录的问题:
INSERT INTO email_tracker_part (SELECT * FROM email_tracker_orig WHERE id > 148893974);
my.cnf 中没有任何提示超时 40 分钟的内容,我在此测试服务器上 运行 查询的时间比这个长,但我有我的解决方案,所以我会关闭它,即使我仍然不清楚根本原因。