我的 MySQL 数据库中有一个包含约 300 万条记录的大表。我试图使用以下查询查找此表中的重复行 -
SELECT package_id
FROM version
WHERE metadata IS NOT NULL AND metadata <> '{}'
GROUP BY package_id, metadata HAVING COUNT(package_id) > 1
此查询在数据库上运行大约需要 23 秒。然而,我们的数据库主机使用 pt-kill 终止任何耗时超过 3 秒的查询。所以我需要找到一种方法来分解这个查询,比如每个子部分都是一个单独的查询,并且每个子部分花费的时间不到 3 秒。仅添加 LIMIT 约束并不能满足查询的需要,那么如何中断查询以处理表的不同部分。
SHOW CREATE TABLE version
的结果
CREATE TABLE `version` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`package_id` bigint(20) unsigned NOT NULL,
`version_number` int(11) unsigned NOT NULL,
`current_state_id` tinyint(2) unsigned NOT NULL,
`md5sum` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_cs NOT NULL DEFAULT '',
`uri` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_cs NOT NULL DEFAULT '',
`filename` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_cs NOT NULL DEFAULT '',
`size` bigint(11) unsigned NOT NULL DEFAULT '0',
`metadata` varchar(1024) CHARACTER SET utf8 COLLATE utf8_general_cs DEFAULT NULL,
`storage_type_id` tinyint(2) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_version_package_id_version_number` (`package_id`,`version_number`),
KEY `idx_version_md5sum` (`md5sum`),
KEY `idx_version_metadata` (`metadata`(255)),
KEY `idx_version_current_state_id` (`current_state_id`),
KEY `storage_type_id` (`storage_type_id`),
CONSTRAINT `_fk_version_current_state_id` FOREIGN KEY (`current_state_id`) REFERENCES `state` (`id`),
CONSTRAINT `_fk_version_package_id` FOREIGN KEY (`package_id`) REFERENCES `package` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3248761 DEFAULT CHARSET=utf8
可以看出,表上有很多索引,包括 Package_id + Version_number 字段组合的索引。问题是这个表只会变得更大,而且我认为即使优化将我拉回到 3 秒范围内也不会扩展。因此,我需要一种方法来对该表进行分区并在不同的部分上运行查询。
最佳答案
提高速度的步骤。
- 创建仅包含 id 列和 package_id 列的表 version_small,并在 package_id 上建立索引。
- 插入 version_small,从版本中选择 id 和 package_id;
- 在上面的优化表上运行原始查询 - 在较小的表上应该会快得多。
或者
- 创建仅包含 id 和 package_id 列以及一个在 package_id 上具有唯一索引的 int 计数器的表 version_small。
- 插入 version_small,从版本中选择 id 和 package_id,在重复键增量计数器上;
- counter>1 的行是包含多个条目的 package_id。
关于mysql - 如何在大表的多个部分中查找重复的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40517054/