我正在尝试优化一个我无法解决的非常古老的查询。我希望存档的结果是,我想在网上商店推荐其他客户对其感兴趣的访问者,即他们与访问者正在查看的产品一起购买的其他内容。
我有一个子查询,但是非常慢,在~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: 感谢您的评论,这里的人是我的答案,他们不适合评论领域。
在上面的查询中使用EXPLAIN我得到了结果。请注意,我在表上没有任何索引(id
- 字段上的主键除外),我想修改查询以使索引受益并在正确的键上放置索引。
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
| 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 |
+----+--------------------+----------+------+---------------+------+---------+------+------+----------------------------------------------+
答案 0 :(得分:1)
要添加两个明显的索引:一个在basketid上,另一个在productid上:然后重试查询和一个新的EXPLAIN以查看正在使用的索引
答案 1 :(得分:1)
除了确保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
。因此,加入速度提高了一个数量级。
答案 2 :(得分:0)
您主要用于在此查询中搜索的两个字段是productid和basketid。
当您搜索productid等于427的记录时,数据库不知道在哪里可以找到此记录。它甚至不知道如果找到一个匹配,那么就不会有另一个匹配的匹配,所以它必须查看整个表,可能有数千个记录。
索引是一个单独的文件,它被排序,并且只包含您有兴趣排序的字段。所以创建一个索引可以节省大量的时间!