2017-01-13 11 views
0

В основном я пытаюсь создать страницу «предложений» на основе интересов пользователя.Подзапрос MySQL в той же таблице убивает производительность

В накопительной таблице хранятся все продукты, которые видят каждый пользователь. Моя идея состояла в том, чтобы выбрать все увиденные продукты всех людей, посетивших увиденные продукты. Я пытался придумать с запросом на некоторое время теперь, но моя лучшая идея собирается

  • а) Несколько запросов
  • б) подзапросов

Вещь, я думаю, что это делать с несколько запросов не масштабируются, если моя таблица растет. С подзапросами у меня был запрос, который уничтожил мою базу данных, хотя, когда я использовал EXPLAIN, все казалось прекрасным (нет таблицы temp, без дисков), но когда я выполнял запрос, который потребовался за минуту, чтобы выполнить ... в таблице с ~ 40k строк. Выполнение запросов один за другим делало то, что я хотел в течение секунды, поэтому я действительно озадачен. Где я совершаю ошибку?

Таблица содержит следующие столбцы идентификатор (Primary), user_id, product_id и кучу ненужных полей

Ниже приведен SQL-запрос я придумал (что убивает мой сервер)

SELECT product_id 
FROM user_behavior 
WHERE user_id 
IN (

    SELECT user_id 
    FROM user_behavior 
    WHERE user_id <> 43456 
    AND product_id 
    IN (

     SELECT product_id 
     FROM user_behavior 
     WHERE user_id =43456 
     GROUP BY product_id 
    ) 
    AND offer_city_id 
    IN (0, 2) 
) 

Как я сказал, работаю объяснить возвращает следующее

| id | select_type   | table    | type    | possible_keys   | key  | key_len | ref  | rows  | Extra      | 
|---- |-------------------- |--------------- |---------------- |------------------- |--------- |--------- |------- |------- |-------------------------- | 
| 1  | PRIMARY    | user_behavior  | index    | NULL     | user_id | 8   | NULL  | 25800  | Using where; using index | 
| 2  | DEPENDENT SUBQUERY | user_behavior  | index_subquery | user_id,user_id_2  | user_id | 4   | func  | 3   | Using where    | 
| 3  | DEPENDENT SUBQUERY | user_behavior  | ref    | user_id,user_id_2  | user_id | 4   | const  | 76  | Using where; using index | 

EDIT: Я сожалею, я не могу представить себе таблицу :(

ответ

1

Не использовать IN (SELECT ...).

Я полностью потерял то, что пытается выполнить запрос, но переход на JOIN и EXISTS, скорее всего, будет частью решения. Возможно, что-то близкое к этому:

SELECT s.product_id 
    FROM user_behavior AS a 
    JOIN user_behavior AS b ON b.user_id = a.user_id 
    WHERE EXISTS (
       SELECT * 
        FROM user_behavior 
        WHERE product_id = b.product_id 
        AND user_id = 43456 
       ) 
     AND b.offer_city_id IN (0, 2) 
     AND b.user_id <> 43456 

и включают в себя 'композитный' INDEX(user_id, product_id) (в любом порядке)

Или, может быть, только это нужно ?? ...

SELECT DISTINCT product_id 
    FROM user_behavior AS b 
    WHERE EXISTS (
       SELECT * 
        FROM user_behavior 
        WHERE product_id = b.product_id 
        AND user_id = 43456 
       ) 
     AND offer_city_id IN (0, 2) 
     AND user_id <> 43456 

Ну, я надеюсь, что вы получите некоторые идеи от этих попыток.

+0

Второй запрос был именно тем, что мне нужно. Я понятия не имею, как работает EXISTS, но я перейду к документации по MySQL и попытаюсь понять ее. Спасибо! – Sk1ppeR

+0

'EXISTS' - это« полу-соединение », в котором он похож на« JOIN », но останавливается, когда находит совпадение. Затем он возвращает только True или False; не вводите в заблуждение '*'. –