同一个表中的MySQL子查询会导致性能下降

时间:2017-01-13 13:01:17

标签: mysql optimization subquery

基本上我正在尝试根据用户兴趣创建“建议”页面。

在累积表中,我存储了每个用户看到的所有产品。我的想法是选择所有看过我看过的产品的人看过的产品。我一直试图提出一段时间的查询,但我最好的想法是

  • a)很少有查询
  • b)子查询

事情是,如果我的表增长,我认为用少量查询来做这件事是不可扩展的。使用子查询我查询破坏了我的数据库,即使我使用EXPLAIN一切似乎都很好(没有临时表,没有磁盘命中)但是当我生成查询时花了一分钟来执行...在~40k的表中行。在一秒钟内逐个运行查询做了我想要的事情,所以我真的很困惑。我在哪里做错了?

该表包含以下列id(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  |

编辑:对不起,我无法想象一张桌子:(

1 个答案:

答案 0 :(得分:1)

请勿使用IN ( SELECT ... )

我对查询尝试的内容感到很遗憾,但切换到JOINEXISTS可能是解决方案的一部分。也许接近这个:

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 

并包含一个&#39;复合材料&#39; 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 

好吧,我希望你从这些尝试中得到一些想法。