SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 05.11.2012 21:03:01

xOpTimuSx
Участник
Зарегистрирован: 05.11.2012
Сообщений: 4

Using temporary при использовании distinct

Здравствуйте! Подскажите пожалуйста! Есть таблица со связью многие ко многим, там хранится связь между продуктами и категориями.

CREATE TABLE `category_products` (
  `category_id` int(10) unsigned NOT NULL,
  `product_id` int(10) unsigned NOT NULL,
  UNIQUE KEY `product_id` (`product_id`,`category_id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `category_products_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE,
  CONSTRAINT `category_products_2` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT

Прив выполнении простенького запроса с distinct

SELECT DISTINCT category_id FROM category_products WHERE product_id IN (100, 200, 300)

, explain выдаёт что исользуется временная таблица.

+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
| id | select_type | table | type  | possible_keys | key        | key_len | ref  | rows | Extra                                     |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+
|  1 | SIMPLE      | cp    | range | product_id    | product_id | 4       | NULL |    4 | Using where; Using index; Using temporary |
+----+-------------+-------+-------+---------------+------------+---------+------+------+-------------------------------------------+

Подскажите пожалуйста, почему так происходит, и как это можно поправить? Заранее спасибо!

Неактивен

 

#2 05.11.2012 21:14:18

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Using temporary при использовании distinct

Потому что вы делаете неявную группировку по category_id. ИМХО, никак не поправить.

Неактивен

 

#3 05.11.2012 21:19:54

xOpTimuSx
Участник
Зарегистрирован: 05.11.2012
Сообщений: 4

Re: Using temporary при использовании distinct

vasya написал:

Потому что вы делаете неявную группировку по category_id. ИМХО, никак не поправить.

Простите, не могли бы вы объяснить что значит не явная группировка?

Неактивен

 

#4 05.11.2012 21:20:04

deadka
Администратор
Зарегистрирован: 14.11.2007
Сообщений: 2422

Re: Using temporary при использовании distinct

Что значит "поправить"? Использование временной таблицы вообще-то ошибкой не является.
Вообще temporary возникает из-за неявной группировки (distinct). Как вариант - можно использовать явную группировку, тем паче у Вас уже и ключик на это создан подходящий.
Но в данном случае MySQL мог бы полностью использовать ключ `product_id`(`product_id`,`category_id`), но range на product_id ( IN даёт тот же эффект, что и range ) не позволяет использовать вторую половинку индекса.

Запрос SELECT category_id FROM t_6222 WHERE product_id = 100 group by category_id; показывает explain без temporary -  Using where; Using index
и индекс используется полностью.

Так что сделайте через union - что-то вроде

SELECT category_id FROM t_6222 WHERE product_id = 100 group by category_id
union
SELECT category_id FROM t_6222 WHERE product_id = 200 group by category_id
union
SELECT category_id FROM t_6222 WHERE product_id = 300 group by category_id;


лучше вряд ли придумаю.


Зеленый свет для слабаков, долги отдают только трусы, тру гики работают только в консоли...

Неактивен

 

#5 05.11.2012 21:39:18

xOpTimuSx
Участник
Зарегистрирован: 05.11.2012
Сообщений: 4

Re: Using temporary при использовании distinct

Т.е. из-за типа связывания range используется только поле "product_id", составного ключа "product_id"?
Подскажите ещё пожалуйста, как узнать какие поля составного ключа используются?

Неактивен

 

#6 05.11.2012 21:44:02

vasya
Архат
MySQL Authorized Developer
Откуда: Орел
Зарегистрирован: 07.03.2007
Сообщений: 5842

Re: Using temporary при использовании distinct

Смотрите на значение колонки key_len
В вашем случае 4 значит используется только первая часть.
`product_id` int(10) unsigned NOT NULL, как раз требует 4 байта для хранения.
Если бы индекс использовался полностью, то было бы 8

Неактивен

 

#7 05.11.2012 21:55:15

xOpTimuSx
Участник
Зарегистрирован: 05.11.2012
Сообщений: 4

Re: Using temporary при использовании distinct

Спасибо всем!!!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson