Не задействуется индекс в подзапросе

e_moon

Новичок
Здравствуйте,

Прошу помочь разобраться! Не могу понять почему не спользуется primary-индекс в основном запросе. Задача - выбрать по одной последней записи с фоткой для каждого пользователя (таковых всего 10, но перебирает все 1489):

Код:
EXPLAIN SELECT * FROM as_data WHERE `id` IN (
SELECT max(`id`) FROM as_data WHERE `photos` LIKE "%jpg%" GROUP BY `user_id` ORDER BY max(`id`)
) ORDER BY `id` DESC
1) PRIMARY as_data ALL NULL 1489 NULL Using where; Using filesort
2) DEPENDENT SUBQUERY as_data index user_id 4 NULL 10 Using where; Using filesort
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Потому что подзапрос вычисляется на каждую строку выборки из основного запроса заново, не?
 

hell0w0rd

Продвинутый новичок
А тут случайно нельзя подзапрос на джоины + having заменить?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
А тут случайно нельзя подзапрос на джоины + having заменить?
кмк, да тут лучше бы вообще легкую денормализацию с каким нибудь "is_active" у аватарок или "active_image_id" у пользователя.
 

e_moon

Новичок
А тут случайно нельзя подзапрос на джоины + having заменить?
Попробовал. Индексы вообще не учитываются. Выборка висит 37-38 сек...

SELECT * FROM as_data WHERE id IN (
SELECT MAX(id)
FROM as_data
INNER JOIN (
SELECT MAX(pubdate) AS maxdate, user_id
FROM as_data
GROUP BY user_id
) AS ms ON as_data.pubdate=ms.maxdate AND as_data.user_id=ms.user_id
GROUP BY as_data.user_id
)
 

e_moon

Новичок
Такой запрос работает и очень шустро:
Код:
SELECT *
FROM (SELECT max(`id`) id FROM as_data WHERE `photos` LIKE "%jpg%" GROUP BY `user_id`) AS r
JOIN as_data AS a ON r.id=a.id
ORDER BY r.`id`
Остался такой вопрос: имеет ли смысл делать индекс на photos (чтобы не заморачиваться с созданием колонки is_avatar)? Тут либо поле пустое, либо содержит путь к изображению.
 

hell0w0rd

Продвинутый новичок
Попробовал. Индексы вообще не учитываются. Выборка висит 37-38 сек...

SELECT * FROM as_data WHERE id IN (
SELECT MAX(id)
FROM as_data
INNER JOIN (
SELECT MAX(pubdate) AS maxdate, user_id
FROM as_data
GROUP BY user_id
) AS ms ON as_data.pubdate=ms.maxdate AND as_data.user_id=ms.user_id
GROUP BY as_data.user_id
)
гм)) я предложил совсем убрать подзапрос. Понятно что если и джойнить с подзапросом - будет еще больше висеть))
 

HraKK

Мудак
Команда форума
Задача - выбрать по одной последней записи с фоткой для каждого пользователя (таковых всего 10, но перебирает все 1489):
Задача не решается.

Вводи денормализованное поле - current photo.
 

Linker

Новичок
А ещё, лично меня, смущает:
Код:
LIKE "%jpg%"
могу побиться об заклад, что-то тут неправильно.
Теоретически, хранить "оригинальное название" можно, наверное, для удобства пользователя, типа что он там загружал и не помнит... Но данные в СУБД, как правило, хранятся раздельно, например типа того:

- путь к файлу (если в этом есть смысл и оно не задано глобально в другом месте)
- уникальное имя файла
- расширение файла
- оригинальное название файла (если этого захотят пользователи, то нам не жалко)
- какая-нибудь метка, флаг, статус, комментарий и т.д. и т.п.
...
здесь могут быть ещё 150 полей если нужно
...
соответственно, эти данные выбираются и "склеиваются" так как нужно и когда нужно.
А хранить всё одной строкой, каждый раз "выкусывая" нужную часть данных... Как-то совсем не по Фэн-шую.
 

fixxxer

К.О.
Партнер клуба
выбросить like, сделать has_photo boolean, индекс (user_id, has_photo), и как-то так
Код:
select * from as_data a inner join (select max(id) as id from as_data where has_photo group by user_id) m on (a.id=m.id)
 
Сверху