MySQL同表中的子查询会降低性能

标签 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  |

编辑:抱歉,我无法可视化表格:(

最佳答案

不要使用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 

并包含一个“复合”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 

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

关于MySQL同表中的子查询会降低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41635245/

相关文章:

php - PDO: 找不到驱动程序 php/mysql

multithreading - 使用 WaitGroups 和 goroutines 优化多线程的正确方法?

php - 如何在单个查询中使用 While 循环编写多个查询?

c# - 求解器基础优化 - 一维装箱

C 根据优化级别给出不同的输出(新示例)

mysql - 选择整行以及第三高的薪水

mysql - SQL 我的子查询永远加载

php - 一张一张更新图片

mysql - 这个用于排名的 MySQL 触发器有什么问题?

mysql - 关于 mysql 的 IN 和 NOT IN 的危险