题
我正在尝试优化一个我无法缠绕头的非常古老的查询。我想存档的结果是,我想在网上店里推荐访客,其他客户对此表示兴趣,即他们与访客正在寻找的产品一起购买了什么。
我有一个子查询,但这是 非常 慢,在〜8 000 000行上需要约15秒。
布局是所有放入用户篮子的产品都保存在桌子中 wsBasket
并被一个 basketid
(在另一个表中与成员关联)。
在此示例中,我想列出用户与Productid 427一起购买的所有最受欢迎的产品,但不列出Productid 427本身。
SELECT productid, SUM(quantity) AS qty
FROM wsBasket
WHERE basketid IN
(SELECT basketid
FROM wsBasket
WHERE productid=427) AND productid!=427
GROUP by productid
ORDER BY qty
DESC LIMIT 0,4;
任何帮助深表感谢!希望至少对某人有任何意义:)
更新1:感谢您的评论,这是我的答案,他们不适合评论场。
在上述查询中使用解释,我得到了fllllll的。请注意,我在表上没有任何索引(除了主键 id
- field),我想修改查询以从索引中受益,并将索引放在正确的键上。
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
| 1 | PRIMARY | wsBasket | ALL | NULL | NULL | NULL | NULL | 2821 | Using where; Using temporary; Using filesort |
| 2 | DEPENDENT SUBQUERY | wsBasket | ALL | NULL | NULL | NULL | NULL | 2821 | Using where |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
解决方案
两个明显的索引要添加:一个在basketid上,另一个是productid:然后重试查询和一个新的解释,以查看正在使用索引
其他提示
以及确保存在合适的索引 productid
和 basketid
, ,您通常会从将查询构造为简单的加入而不是子查询中,尤其是在MySQL中。
SELECT b1.productid, SUM(b1.quantity) AS qty
FROM wsBasket AS b0
JOIN wsBasket AS b1 ON b1.basketid=b0.basketid
WHERE b0.productid=427 AND b1.productid<>427
GROUP BY b1.productid
ORDER BY qty DESC
LIMIT 4
对我来说,在一个可能相似的数据集上,加入导致了两个 select_type: SIMPLE
行中的行 EXPLAIN
输出,而子查询方法吐出了可怕的表现 DEPENDENT SUBQUERY
. 。因此,连接的速度更快。
您主要在此查询中用于搜索的两个字段是Productid和BasketId。
当您搜索具有相当于427的记录时,数据库不知道在哪里可以找到此记录。甚至不知道它确实找到了一个匹配,就不会有另一个匹配的匹配,因此必须浏览整个桌子,可能是数千个记录。
索引是一个分类的单独文件,仅包含您有兴趣分类的字段。因此,创建索引节省了巨大的时间!