SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 02.03.2012 21:02:37

addddd
Участник
Зарегистрирован: 02.03.2012
Сообщений: 3

Оптимизация выборки картинок по тегам

Помогите, пожалуйста, оптимизировать запрос. Есть таблица с картинками images, есть таблица с тегами tags, связывает их таблица img2tag. Требуется найти картинки, с определенными тегами, например запрос
"речка, лес"
должен выдать картинки с тегами
"речка, лес, осень, птицы"
"речка, грибы, лес"
"закат, речка, журавли, лес"
делаю так

SELECT * FROM images WHERE imid IN (SELECT image_id FROM img2tag WHERE tag_id = 202) AND imid IN (SELECT image_id FROM img2tag WHERE tag_id = 30);
^ выполняется несколько секунд

SELECT * FROM images WHERE imid IN (SELECT image_id FROM img2tag WHERE tag_id IN(30,202) GROUP BY image_id HAVING count(image_id) = 2);
^с сегодняшним размером таблицы уходит в зависон, когда картинок было мало выполнялся около минуты
оно бы и бросить второй вариант, но вложенный запрос

SELECT image_id FROM img2tag WHERE tag_id IN(30,202) GROUP BY image_id HAVING count(image_id) = 2;
^выполняется за 0.06 секунды. не понимаю почему мускул так тормозит, ведь рядов во вложенном запросе во втором варианте получается на порядок меньше ~200, когда как в первом по ~2000


Прикрепленные файлы:
Attachment Icon database.sql, Размер: 1,246 байт, Скачано: 1,129

Неактивен

 

#2 03.03.2012 00:16:41

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

Re: Оптимизация выборки картинок по тегам

Перепишите запрос через join. На данный момент подзапрос в IN выполняется для каждой строки внешнего запроса, несмотря на то, что они не зависимы и выполняться он должен только один раз.

Неактивен

 

#3 03.03.2012 16:46:45

addddd
Участник
Зарегистрирован: 02.03.2012
Сообщений: 3

Re: Оптимизация выборки картинок по тегам

вон оно что. переписал, получилось быстрее

SELECT images.* FROM img2tag LEFT JOIN images ON imid=image_id WHERE tag_id IN(30,202) GROUP BY image_id HAVING count(image_id) = 2;
0.1410 сек

но в 2 запроса все равно быстрее получается
SELECT image_id FROM img2tag WHERE tag_id IN(202,30) GROUP BY image_id HAVING count(image_id) = 2;
SELECT * FROM images WHERE imid IN (0,106885,110569,110726,113853,114139,114146.....[42 индекса]) LIMIT 0,50;
PHP: 8.2969665527344E-5 MySQL: 0.063997983932495

по эксплейнам первый запрос одинаковый получается
в один запрос
id      sel_type      table      type      possible_keys      key      key_len      ref      rows      Extra
1    SIMPLE    img2tag    range    ind2    ind2    4    NULL    42751    Using where; Using index; Using temporary; Using f...
1    SIMPLE    images    eq_ref    PRIMARY    PRIMARY    4    pixiv.img2tag.image_id    1    

в два запроса
1    SIMPLE    img2tag    range    ind2    ind2    4    NULL    42751    Using where; Using index; Using temporary; Using f...

1    SIMPLE    images    range    PRIMARY    PRIMARY    4    NULL    42    Using where

Неактивен

 

#4 04.03.2012 00:49:13

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

Re: Оптимизация выборки картинок по тегам

А зачем вам left join?


SELECT images.* FROM images join
(SELECT image_id FROM img2tag WHERE tag_id IN(202,30) GROUP BY image_id HAVING count(image_id) = 2) t
ON imid=t.image_id;

Неактивен

 

#5 04.03.2012 01:00:18

addddd
Участник
Зарегистрирован: 02.03.2012
Сообщений: 3

Re: Оптимизация выборки картинок по тегам

о, спасибо, не знал что есть просто join. выполняется еще быстрее чем в два запроса

Неактивен

 

Board footer

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