У меня есть таблица animals
с 3 миллионами записей. В таблице, среди нескольких других столбцов, есть столбцы id
, name
и owner_id
. У меня есть таблица animal_breeds
с 2,5 миллионами записей. В таблице есть только столбцы animal_id
и breed
.
Я пытаюсь найти различные breed
значения, которые связаны с конкретным owner_id
, но запрос занимает около 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_id_index
для таблицы animal_breeds
является избыточным из-за уникального ключа в таблице, но мы можем пока игнорировать его, пока это не вызывает проблемы:)
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
Любая помощь будет оценена. Спасибо!