【发布时间】:2019-10-22 12:46:54
【问题描述】:
我有一个包含大约 300 万条记录的 animals 表。除了其他几列之外,该表还有一个id、name 和owner_id 列。我有一个 animal_breeds 表,大约有 250 万条记录。该表只有animal_id 和breed 列。
我正在尝试查找与特定 owner_id 关联的不同 breed 值,但查询需要 20 秒左右。这是查询:
SELECT DISTINCT `breed`
FROM `animal_breeds`
INNER JOIN `animals` ON `animals`.`id` = `animal_breeds`.`animal_id`
WHERE `animals`.`owner_id` = ? ;
这些表具有所有适当的索引。我无法通过将breed 列添加到animals 表来对表进行非规范化,因为可以为动物分配多个品种。我对其他一些具有一对多关系的大表也有这个问题。
有没有更高效的方法来实现我正在寻找的东西?这似乎是一个非常简单的问题,但除了预先计算和缓存结果之外,我似乎无法找出实现这一目标的最佳方法。
这是我的查询的解释输出。注意Using temporary
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 "SIMPLE" "a" NULL "ref" "PRIMARY,animals_animal_id_index" "animals_animal_id_index" "153" "const" 1126303 100.00 "Using index; Using temporary"
1 "SIMPLE" "ab" NULL "ref" "animal_breeds_animal_id_breed_unique,animal_breeds_animal_id_index,animal_breeds_breed_index" "animal_breeds_animal_id_breed_unique" "5" "pedigreeonline.a.id" 1 100.00 "Using index"
根据要求,这里是创建表语句(我从animals 表中省略了一些不相关的列和索引)。我相信animal_breeds 表上的animal_breeds_animal_id_index 索引是多余的,因为表上有唯一键,但我们现在可以忽略它,只要它不会导致问题:)
CREATE TABLE `animals` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
`owner_id` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `animals_animal_id_index` (`owner_id`,`id`),
KEY `animals_name_index` (`name`),
) ENGINE=InnoDB AUTO_INCREMENT=2470843 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `animal_breeds` (
`animal_id` int(10) unsigned DEFAULT NULL,
`breed` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
UNIQUE KEY `animal_breeds_animal_id_breed_unique` (`animal_id`,`breed`),
KEY `animal_breeds_animal_id_index` (`animal_id`),
KEY `animal_breeds_breed_index` (`breed`),
CONSTRAINT `animal_breeds_animal_id_foreign` FOREIGN KEY (`animal_id`) REFERENCES `animals` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
任何帮助将不胜感激。谢谢!
【问题讨论】:
-
CREATE TABLE 语句会很好
-
使用 CREATE TABLE 语句更新
-
删除密钥
animal_breeds_animal_id_index(animal_id), -
是的,我意识到这是多余的。自从编辑我的答案后,我已经放弃了密钥,但这对查询速度没有帮助。
标签: mysql sql performance join distinct