2014-02-01 3 views
0

Предположим, что мы имеем следующий сценарий: 2 объекта; пользователей, изображений.
Пользователи могут видеть изображения, а также следовать друг за другом. (Итак, у нас есть 2 реляционных таблицы, user_likes и следуйте, где кому понравилось, и кто следует, кто хранится)Как оптимизировать результаты поиска по отдельному пользователю

Итак, мы (представлены пользователем и) хотим выполнить поиск для получения изображений, которые нравятся наших друзей и назвали «cat.jpg».

В SQL-то подобное будет выглядеть

SElECT DISTINCT(images.id) 
FROM images 
JOIN likes ON likes.image_id = images.id 
JOIN 
    (SELECT follow.following_id 
    FROM follow 
    WHERE follow.follower_id = MY_ID) as following 
ON following.following_id = likes.user_id 
WHERE images.name = "cat.jpg" 
ORDER BY images.date DESC 
LIMIT 0, 20 

выше запрос возвращает 20 последних уникальных идентификаторах изображений пользователей мы следующие понравившиеся и которые (образы) под названием «кот. JPG».

Мой вопрос ... Как оптимизировать эту процедуру?

Первой мыслью, которая приходит мне на ум, является кеширование, но если другой пользователь ищет «cat.jpg», ему будут предоставлены разные результаты (потому что он/она будет следовать за другим набором пользователей). Поэтому кэширование в этом конкретном сценарии кажется дорогостоящим, поскольку может быть огромное количество возможных поисковых ключевых слов и огромный набор комбинаций пользователей и пользователей. Это жизнеспособное решение? Если этот пользователь больше никогда не ищет «cat.jpg», то кэширование ответа будет просто пустой тратой памяти.

Как правило, я видел людей, предлагающих использовать Redis или даже Memcached для хранения списков обновлений или записей в социальных сетях для каждого пользователя, но в сценарии поиска что-то вроде этого кажется коротким. Нет?

Любые предложения, советы или ссылки с ресурсами, обсуждающими похожие проблемы и подходы, приветствуются!

ответ

1

Это ваш запрос (упрощенный, используя псевдонимы таблиц):

SElECT DISTINCT i.id 
FROM images i JOIN 
    likes l 
    ON l.image_id = i.id JOIN 
    (SELECT f.following_id 
     FROM follow f 
     WHERE f.follower_id = MY_ID 
    ) as f 
    ON f.following_id = l.user_id 
WHERE i.name = 'cat.jpg' 
ORDER BY i.date DESC 
LIMIT 0, 20; 

Как мы можем сделать его работать быстрее? Ну, во-первых, подзапрос не требуется:

SElECT DISTINCT i.id 
FROM images i JOIN 
    likes l 
    ON l.image_id = i.id JOIN 
    follow f 
    ON f.following_id = l.user_id and 
     f.follower_id = MY_ID 
WHERE i.name = 'cat.jpg' 
ORDER BY i.date DESC 
LIMIT 0, 20; 

Во-вторых, следующие показатели могут помочь производительности:

images(name, date); 
likes(image_id, user_id); 
follow(user_id, follower_id); 
0

Да, это простое решение. Это гораздо больше усилий, чтобы найти все комбинации, возможно, невозможно. Эта же проблема заключается в кратчайшем пути в задаче графа. Или самый короткий путь AZ.

Смежные вопросы