基本上,我正在尝试根据用户兴趣创建一个“建议”页面。
在一个累积表中,我存储了每个用户看到的所有产品。我的想法是选择所有访问过我所见过的产品的人的所有已见过的产品。我已经尝试提出一个查询有一段时间了,但我最好的想法是
- 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 ... )
。
我对查询试图执行的操作感到非常困惑,但切换到 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
好吧,我希望您能从这些尝试中得到一些想法。
关于MySQL同表中的子查询会降低性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41635245/